<commit_before>//!Bindings and rewrites of include/linux/time.h and include/linux/time64.h

extern crate linux_api;

use linux_api::*;

#[link(name="rt")]
extern "C" {
    //Dummy section to link RT, but probably shouldn't link everything to it
}

//First, we do external functions
extern "C" {

    ///Gets the current time as seconds from the UNIX epoch
    pub fn time(t: *mut time_t) -> time_t;

    pub fn difftime(time1: time_t, time0: time_t) -> c_double;

}

///Checks to see if two timespecs are equal
pub fn timespec_equal(a: &timespec, b: &timespec) -> c_int {
    return ((a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec)) as c_int;
}

///Compares two timespecs
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timespec_compare(lhs: &timespec, rhs: &timespec) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_nsec - rhs.tv_nsec) as c_int;
}

///Compares two timevals
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timeval_compare(lhs: &timeval, rhs: &timeval) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_usec - rhs.tv_usec) as c_int;
}

//TODO: mktime64
//TODO: mktime

///Sets the data contained in the borrowed `timespec` ts to normalized values
pub fn set_normalized_timespec(ts: &mut timespec, sec: time_t, nsec: i64) {
    let mut realsec = sec;
    let mut realnsec = nsec;

    while realnsec >= NSEC_PER_SEC {
        //TODO: Check to see if this gets optimized and, if so, force it not to as per kernel definition
        realnsec -= NSEC_PER_SEC;
        realsec += 1;
    }

    while realnsec < 0 {
        //Ditto
        realnsec += NSEC_PER_SEC;
        realsec -= 1;
    }

    ts.tv_sec = realsec;
    ts.tv_nsec = realnsec;
}

//TODO: timespec_add_safe, timespec_sub

///Adds two timespecs together, returning the result as a new timespec
pub fn timespec_add(lhs: &timespec, rhs: &timespec) -> timespec {
    let mut ts_delta: timespec = timespec { tv_sec:0, tv_nsec: 0 };
    set_normalized_timespec(&mut ts_delta, lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec);
    ts_delta
}

///Subtracts rhs from lhs, returning the difference as a new timespec
pub fn timespec_sub(lhs: &timespec, rhs: &timespec) -> timespec {
    let mut ts_delta: timespec = timespec { tv_sec: 0, tv_nsec: 0 };
    set_normalized_timespec(&mut ts_delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);
    ts_delta
}

///Checks to see if a timespec is valid
pub fn timespec_valid(ts: &timespec) -> bool {
    //Dates before 1970 are bogus
    if ts.tv_sec < 0 {
        return false;
    }

    //Can't have more nanoseconds than a second
    if ts.tv_nsec >= NSEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

///Checks to see if a timespec is valid according to stricter rules
pub fn timespec_valid_strict(ts: &timespec) -> bool {
    if !timespec_valid(ts) {
        return false;
    }

    //Okay, we've validated it quickly
    //Disallow values that could overflow ktime_t
    if ts.tv_sec >= KTIME_SEC_MAX {
        return false;
    }

    return true;
}

///Checks to see if a timeval is valid
pub fn timeval_valid(tv: &timeval) -> bool {
    //Dates before 1970 are bogus
    if tv.tv_sec < 0 {
        return false;
    }

    //Can't have more microseconds than a second
    if tv.tv_usec >= USEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

///Creates a time64_t from the supplied year, month, day, hour, minute, and second
pub fn mktime64(year0: c_uint, mon0: c_uint, day: c_uint, hour: c_uint, min: c_uint, sec: c_uint) -> time64_t {

    let mut mon = mon0;
    let mut year = year0;

    //The kernel tells us to do this. It's basically treating Jan and Feb as months 11 and 12, then pulling the others up by two. Leap year, perhaps?

    let mut _mon = mon as c_int;

    _mon -= 2;

    if _mon <= 0 {
        mon += 10; //Because we didn't take the two off)
        year -= 1;
    } else {
        mon -= 2; //Because we can
    }

    //I'm trusting you here, kernel developers! This is ugly but it had better work

    let mut result: time64_t = 0;

    result = (year/4 - year/100 + year/400 + 367*mon/12 + day) as i64;
    result += year as i64 * 365;
    result -= 719499;
    result *= 24;
    result += hour as i64;
    result *= 60;
    result += min as i64;
    result *= 60;
    result += sec as i64;

    //result += (((((year / 4) - (year / 100) + (year / 400) + (367*mon/12) + day + (year * 365)) * 24 + hour) * 60 + min) * 60 + sec) as time64_t;

    return result;

}

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

    #[test]
    fn test_time_ffi() {
        let mut atime: time_t = 0;

        unsafe { atime = time(::std::ptr::null_mut()); }

        assert!(atime >= 1437309103); //Time of first testing
    }

    #[test]
    fn test_difftime_ffi() {
        let mut atime: time_t = 0;

        unsafe { atime = time(::std::ptr::null_mut()); }

        let anothertime: time_t = atime - 100;

        let mut result: c_double = 0f64;

        unsafe { result = difftime(atime, anothertime); }

        assert_eq!(100f64, result);

        unsafe { result = difftime(anothertime, atime); }

        assert_eq!(-100f64, result);
    }

    #[test]
    fn test_timespec_valid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: 4262 };

        assert!(timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_seconds_valid() {
        let atime: timespec = timespec { tv_sec: KTIME_SEC_MAX + 365, tv_nsec: 4262 };

        assert!(!timespec_valid_strict(&atime));
    }

    #[test]
    fn test_timespec_before_1970_invalid() {
        let atime: timespec = timespec { tv_sec: -63, tv_nsec: 4262 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_nanoseconds_invalid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: NSEC_PER_SEC + 2 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timeval_valid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: 4262 };

        assert!(timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_before_1970_invalid() {
        let atime: timeval = timeval { tv_sec: -63, tv_usec: 4262 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_too_many_nanoseconds_invalid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: USEC_PER_SEC + 2 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timespec_equal_when_equal() {
        let one: timespec = timespec { tv_sec: 77, tv_nsec: 77 };
        let two: timespec = timespec { tv_sec: 77, tv_nsec: 77 };

        assert_eq!(1, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_equal_when_inequal() {
        let one: timespec = timespec { tv_sec: 0, tv_nsec: 266 };
        let two: timespec = timespec { tv_sec: 4, tv_nsec: 0 };

        assert_eq!(0, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_compare_same() {
        let one = timespec { tv_sec: 10, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(0, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_larger() {
        let one = timespec { tv_sec: 11, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_smaller() {
        let one = timespec { tv_sec: 9, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(-1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_same() {
        let one = timeval { tv_sec: 10, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(0, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_larger() {
        let one = timeval { tv_sec: 11, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(1, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_smaller() {
        let one = timeval { tv_sec: 9, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(-1, timeval_compare(&one, &two));
    }

    #[test]
    fn test_normalized_timespec_many_nanos() {
        let mut spec: timespec = timespec { tv_sec: 0, tv_nsec: 0 };

        set_normalized_timespec(&mut spec, 10, NSEC_PER_SEC * 20);

        assert_eq!(30, spec.tv_sec);
        assert_eq!(0, spec.tv_nsec);
    }

    #[test]
    fn test_normalized_timespec_negative_nanos() {
        let mut spec: timespec = timespec { tv_sec: 0, tv_nsec: 0 };

        set_normalized_timespec(&mut spec, 5, -800);

        assert_eq!(4, spec.tv_sec);
        assert_eq!(NSEC_PER_SEC - 800, spec.tv_nsec);
    }

    #[test]
    fn test_timespec_add_simple() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 30, tv_nsec: 580 };

        let delta = timespec_add(&lhs, &rhs);

        assert_eq!(110, delta.tv_sec);
        assert_eq!(1080, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_add_manynanos() {
        let lhs = timespec { tv_sec: 80, tv_nsec: NSEC_PER_SEC / 2 };
        let rhs = timespec { tv_sec: 30, tv_nsec: (NSEC_PER_SEC / 2) + 400 };

        let delta = timespec_add(&lhs, &rhs);

        assert_eq!(111, delta.tv_sec);
        assert_eq!(400, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_sub_simple() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 30, tv_nsec: 580 };

        let delta = timespec_sub(&lhs, &rhs);

        assert_eq!(49, delta.tv_sec);
        assert_eq!(NSEC_PER_SEC - 80, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_sub_bad() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 1030, tv_nsec: 580 };

        let delta = timespec_sub(&lhs, &rhs);

        assert_eq!(-951, delta.tv_sec);
        assert_eq!(NSEC_PER_SEC - 80, delta.tv_nsec);
    }

    #[test]
    fn test_mktime64_known_dates() {
        let apocalypse2012: time64_t = 1356048000;
        let sequential: time64_t = 1234567890;

        assert_eq!(apocalypse2012, mktime64(2012, 12, 21, 00, 0, 0));
        assert_eq!(sequential, mktime64(2009, 2, 13, 23, 31, 30));
    }

}<commit_msg>Add gettimeofday and settimeofday, and test gettimeofday<commit_after>//!Bindings and rewrites of include/linux/time.h and include/linux/time64.h

extern crate linux_api;

use linux_api::*;

#[link(name="rt")]
extern "C" {
    //Dummy section to link RT, but probably shouldn't link everything to it
}

//First, we do external functions
extern "C" {

    ///Gets the current time as seconds from the UNIX epoch
    pub fn time(t: *mut time_t) -> time_t;

    ///Calculates the difference, in seconds, between two values of time_t
    pub fn difftime(time1: time_t, time0: time_t) -> c_double;

    ///Gets the time of day in the specified timezone and place it into the timeval
    ///
    ///Please use std::ptr::null_mut() for tz on Linux!
    pub fn gettimeofday(tv: *mut timeval, tz: *mut timezone) -> c_int;

    ///Sets the time of day from the timeval and applies rules from the timezone to it
    ///
    ///Please use std::ptr::null() for tz on Linux!
    pub fn settimeofday(tv: *const timeval, tz: *const timezone) -> c_int;

}

///Checks to see if two timespecs are equal
pub fn timespec_equal(a: &timespec, b: &timespec) -> c_int {
    return ((a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec)) as c_int;
}

///Compares two timespecs
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timespec_compare(lhs: &timespec, rhs: &timespec) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_nsec - rhs.tv_nsec) as c_int;
}

///Compares two timevals
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timeval_compare(lhs: &timeval, rhs: &timeval) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_usec - rhs.tv_usec) as c_int;
}

//TODO: mktime64
//TODO: mktime

///Sets the data contained in the borrowed `timespec` ts to normalized values
pub fn set_normalized_timespec(ts: &mut timespec, sec: time_t, nsec: i64) {
    let mut realsec = sec;
    let mut realnsec = nsec;

    while realnsec >= NSEC_PER_SEC {
        //TODO: Check to see if this gets optimized and, if so, force it not to as per kernel definition
        realnsec -= NSEC_PER_SEC;
        realsec += 1;
    }

    while realnsec < 0 {
        //Ditto
        realnsec += NSEC_PER_SEC;
        realsec -= 1;
    }

    ts.tv_sec = realsec;
    ts.tv_nsec = realnsec;
}

//TODO: timespec_add_safe, timespec_sub

///Adds two timespecs together, returning the result as a new timespec
pub fn timespec_add(lhs: &timespec, rhs: &timespec) -> timespec {
    let mut ts_delta: timespec = timespec { tv_sec:0, tv_nsec: 0 };
    set_normalized_timespec(&mut ts_delta, lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec);
    ts_delta
}

///Subtracts rhs from lhs, returning the difference as a new timespec
pub fn timespec_sub(lhs: &timespec, rhs: &timespec) -> timespec {
    let mut ts_delta: timespec = timespec { tv_sec: 0, tv_nsec: 0 };
    set_normalized_timespec(&mut ts_delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);
    ts_delta
}

///Checks to see if a timespec is valid
pub fn timespec_valid(ts: &timespec) -> bool {
    //Dates before 1970 are bogus
    if ts.tv_sec < 0 {
        return false;
    }

    //Can't have more nanoseconds than a second
    if ts.tv_nsec >= NSEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

///Checks to see if a timespec is valid according to stricter rules
pub fn timespec_valid_strict(ts: &timespec) -> bool {
    if !timespec_valid(ts) {
        return false;
    }

    //Okay, we've validated it quickly
    //Disallow values that could overflow ktime_t
    if ts.tv_sec >= KTIME_SEC_MAX {
        return false;
    }

    return true;
}

///Checks to see if a timeval is valid
pub fn timeval_valid(tv: &timeval) -> bool {
    //Dates before 1970 are bogus
    if tv.tv_sec < 0 {
        return false;
    }

    //Can't have more microseconds than a second
    if tv.tv_usec >= USEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

///Creates a time64_t from the supplied year, month, day, hour, minute, and second
pub fn mktime64(year0: c_uint, mon0: c_uint, day: c_uint, hour: c_uint, min: c_uint, sec: c_uint) -> time64_t {

    let mut mon = mon0;
    let mut year = year0;

    //The kernel tells us to do this. It's basically treating Jan and Feb as months 11 and 12, then pulling the others up by two. Leap year, perhaps?

    let mut _mon = mon as c_int;

    _mon -= 2;

    if _mon <= 0 {
        mon += 10; //Because we didn't take the two off)
        year -= 1;
    } else {
        mon -= 2; //Because we can
    }

    //I'm trusting you here, kernel developers! This is ugly but it had better work

    let mut result: time64_t = 0;

    result = (year/4 - year/100 + year/400 + 367*mon/12 + day) as i64;
    result += year as i64 * 365;
    result -= 719499;
    result *= 24;
    result += hour as i64;
    result *= 60;
    result += min as i64;
    result *= 60;
    result += sec as i64;

    //result += (((((year / 4) - (year / 100) + (year / 400) + (367*mon/12) + day + (year * 365)) * 24 + hour) * 60 + min) * 60 + sec) as time64_t;

    return result;

}

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

    #[test]
    fn test_time_ffi() {
        let mut atime: time_t = 0;

        unsafe { atime = time(::std::ptr::null_mut()); }

        assert!(atime >= 1437309103); //Time of first testing
    }

    #[test]
    fn test_difftime_ffi() {
        let mut atime: time_t = 0;

        unsafe { atime = time(::std::ptr::null_mut()); }

        let anothertime: time_t = atime - 100;

        let mut result: c_double = 0f64;

        unsafe { result = difftime(atime, anothertime); }

        assert_eq!(100f64, result);

        unsafe { result = difftime(anothertime, atime); }

        assert_eq!(-100f64, result);
    }

    #[test]
    fn test_gettimeofday_ffi() {
        let mut time = timeval { tv_sec: 0, tv_usec: 0 };

        let raw_time = &mut time as *mut timeval;

        unsafe {
            let result: c_int = gettimeofday(raw_time, ::std::ptr::null_mut());
            assert_eq!(0, result);
        }

        assert!(!raw_time.is_null());

        assert!(time.tv_sec >= 1437310400); //At time of testing

    }

    #[test]
    fn test_timespec_valid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: 4262 };

        assert!(timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_seconds_valid() {
        let atime: timespec = timespec { tv_sec: KTIME_SEC_MAX + 365, tv_nsec: 4262 };

        assert!(!timespec_valid_strict(&atime));
    }

    #[test]
    fn test_timespec_before_1970_invalid() {
        let atime: timespec = timespec { tv_sec: -63, tv_nsec: 4262 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_nanoseconds_invalid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: NSEC_PER_SEC + 2 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timeval_valid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: 4262 };

        assert!(timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_before_1970_invalid() {
        let atime: timeval = timeval { tv_sec: -63, tv_usec: 4262 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_too_many_nanoseconds_invalid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: USEC_PER_SEC + 2 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timespec_equal_when_equal() {
        let one: timespec = timespec { tv_sec: 77, tv_nsec: 77 };
        let two: timespec = timespec { tv_sec: 77, tv_nsec: 77 };

        assert_eq!(1, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_equal_when_inequal() {
        let one: timespec = timespec { tv_sec: 0, tv_nsec: 266 };
        let two: timespec = timespec { tv_sec: 4, tv_nsec: 0 };

        assert_eq!(0, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_compare_same() {
        let one = timespec { tv_sec: 10, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(0, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_larger() {
        let one = timespec { tv_sec: 11, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_smaller() {
        let one = timespec { tv_sec: 9, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(-1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_same() {
        let one = timeval { tv_sec: 10, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(0, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_larger() {
        let one = timeval { tv_sec: 11, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(1, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_smaller() {
        let one = timeval { tv_sec: 9, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(-1, timeval_compare(&one, &two));
    }

    #[test]
    fn test_normalized_timespec_many_nanos() {
        let mut spec: timespec = timespec { tv_sec: 0, tv_nsec: 0 };

        set_normalized_timespec(&mut spec, 10, NSEC_PER_SEC * 20);

        assert_eq!(30, spec.tv_sec);
        assert_eq!(0, spec.tv_nsec);
    }

    #[test]
    fn test_normalized_timespec_negative_nanos() {
        let mut spec: timespec = timespec { tv_sec: 0, tv_nsec: 0 };

        set_normalized_timespec(&mut spec, 5, -800);

        assert_eq!(4, spec.tv_sec);
        assert_eq!(NSEC_PER_SEC - 800, spec.tv_nsec);
    }

    #[test]
    fn test_timespec_add_simple() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 30, tv_nsec: 580 };

        let delta = timespec_add(&lhs, &rhs);

        assert_eq!(110, delta.tv_sec);
        assert_eq!(1080, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_add_manynanos() {
        let lhs = timespec { tv_sec: 80, tv_nsec: NSEC_PER_SEC / 2 };
        let rhs = timespec { tv_sec: 30, tv_nsec: (NSEC_PER_SEC / 2) + 400 };

        let delta = timespec_add(&lhs, &rhs);

        assert_eq!(111, delta.tv_sec);
        assert_eq!(400, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_sub_simple() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 30, tv_nsec: 580 };

        let delta = timespec_sub(&lhs, &rhs);

        assert_eq!(49, delta.tv_sec);
        assert_eq!(NSEC_PER_SEC - 80, delta.tv_nsec);
    }

    #[test]
    fn test_timespec_sub_bad() {
        let lhs = timespec { tv_sec: 80, tv_nsec: 500 };
        let rhs = timespec { tv_sec: 1030, tv_nsec: 580 };

        let delta = timespec_sub(&lhs, &rhs);

        assert_eq!(-951, delta.tv_sec);
        assert_eq!(NSEC_PER_SEC - 80, delta.tv_nsec);
    }

    #[test]
    fn test_mktime64_known_dates() {
        let apocalypse2012: time64_t = 1356048000;
        let sequential: time64_t = 1234567890;

        assert_eq!(apocalypse2012, mktime64(2012, 12, 21, 00, 0, 0));
        assert_eq!(sequential, mktime64(2009, 2, 13, 23, 31, 30));
    }

}<|endoftext|>


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

use collections::hashmap::HashMap;
use geom::size::Size2D;
use layers::platform::surface::NativePaintingGraphicsContext;
use servo_msg::compositor_msg::Tile;
use std::hash::Hash;
use std::hash::sip::SipState;
use std::mem;

/// This is a struct used to store buffers when they are not in use.
/// The render task can quickly query for a particular size of buffer when it
/// needs it.
pub struct BufferMap<T> {
    /// A HashMap that stores the Buffers.
    map: HashMap<BufferKey, BufferValue<T>>,
    /// The current amount of memory stored by the BufferMap's buffers.
    mem: uint,
    /// The maximum allowed memory. Unused buffers will be deleted
    /// when this threshold is exceeded.
    max_mem: uint,
    /// A monotonically increasing counter to track how recently tile sizes were used.
    counter: uint,
}

/// A key with which to store buffers. It is based on the size of the buffer.
struct BufferKey([uint, ..2]);

impl Hash for BufferKey {
    fn hash(&self, state: &mut SipState) {
        let BufferKey(ref bytes) = *self;
        bytes.as_slice().hash(state);
    }
}

impl Eq for BufferKey {
    fn eq(&self, other: &BufferKey) -> bool {
        let BufferKey(s) = *self;
        let BufferKey(o) = *other;
        s[0] == o[0] && s[1] == o[1]
    }
}

impl TotalEq for BufferKey {
    fn equals(&self, other: &BufferKey) -> bool {
        self.eq(other)
    }
}

/// Create a key from a given size
impl BufferKey {
    fn get(input: Size2D<uint>) -> BufferKey {
        BufferKey([input.width, input.height])
    }
}

/// A helper struct to keep track of buffers in the HashMap
struct BufferValue<T> {
    /// An array of buffers, all the same size
    buffers: ~[T],
    /// The counter when this size was last requested
    last_action: uint,
}

impl<T: Tile> BufferMap<T> {
    // Creates a new BufferMap with a given buffer limit.
    pub fn new(max_mem: uint) -> BufferMap<T> {
        BufferMap {
            map: HashMap::new(),
            mem: 0u,
            max_mem: max_mem,
            counter: 0u,
        }
    }

    /// Insert a new buffer into the map.
    pub fn insert(&mut self, graphics_context: &NativePaintingGraphicsContext, new_buffer: T) {
        let new_key = BufferKey::get(new_buffer.get_size_2d());

        // If all our buffers are the same size and we're already at our
        // memory limit, no need to store this new buffer; just let it drop.
        if self.mem + new_buffer.get_mem() > self.max_mem && self.map.len() == 1 &&
            self.map.contains_key(&new_key) {
            return;
        }

        self.mem += new_buffer.get_mem();
        // use lazy insertion function to prevent unnecessary allocation
        let counter = &self.counter;
        self.map.find_or_insert_with(new_key, |_| BufferValue {
            buffers: ~[],
            last_action: *counter
        }).buffers.push(new_buffer);

        let mut opt_key: Option<BufferKey> = None;
        while self.mem > self.max_mem {
            let old_key = match opt_key {
                Some(key) => key,
                None => {
                    match self.map.iter().min_by(|&(_, x)| x.last_action) {
                        Some((k, _)) => *k,
                        None => fail!("BufferMap: tried to delete with no elements in map"),
                    }
                }
            };
            if {
                let list = &mut self.map.get_mut(&old_key).buffers;
                let condemned_buffer = list.pop().take_unwrap();
                self.mem -= condemned_buffer.get_mem();
                condemned_buffer.destroy(graphics_context);
                list.is_empty()
            }
            { // then
                self.map.pop(&old_key); // Don't store empty vectors!
                opt_key = None;
            } else {
                opt_key = Some(old_key);
            }
        }
    }

    // Try to find a buffer for the given size.
    pub fn find(&mut self, size: Size2D<uint>) -> Option<T> {
        let mut flag = false; // True if key needs to be popped after retrieval.
        let key = BufferKey::get(size);
        let ret = match self.map.find_mut(&key) {
            Some(ref mut buffer_val) => {
                buffer_val.last_action = self.counter;
                self.counter += 1;

                let buffer = buffer_val.buffers.pop().take_unwrap();
                self.mem -= buffer.get_mem();
                if buffer_val.buffers.is_empty() {
                    flag = true;
                }
                Some(buffer)
            }
            None => None,
        };

        if flag {
            self.map.pop(&key); // Don't store empty vectors!
        }

        ret
    }

    /// Destroys all buffers.
    pub fn clear(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        let map = mem::replace(&mut self.map, HashMap::new());
        for (_, value) in map.move_iter() {
            for tile in value.buffers.move_iter() {
                tile.destroy(graphics_context)
            }
        }
        self.mem = 0
    }
}
<commit_msg>auto merge of #2068 : mbrubeck/servo/1187-buffer-destroy, r=larsbergstrom<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use collections::hashmap::HashMap;
use geom::size::Size2D;
use layers::platform::surface::NativePaintingGraphicsContext;
use servo_msg::compositor_msg::Tile;
use std::hash::Hash;
use std::hash::sip::SipState;
use std::mem;

/// This is a struct used to store buffers when they are not in use.
/// The render task can quickly query for a particular size of buffer when it
/// needs it.
pub struct BufferMap<T> {
    /// A HashMap that stores the Buffers.
    map: HashMap<BufferKey, BufferValue<T>>,
    /// The current amount of memory stored by the BufferMap's buffers.
    mem: uint,
    /// The maximum allowed memory. Unused buffers will be deleted
    /// when this threshold is exceeded.
    max_mem: uint,
    /// A monotonically increasing counter to track how recently tile sizes were used.
    counter: uint,
}

/// A key with which to store buffers. It is based on the size of the buffer.
struct BufferKey([uint, ..2]);

impl Hash for BufferKey {
    fn hash(&self, state: &mut SipState) {
        let BufferKey(ref bytes) = *self;
        bytes.as_slice().hash(state);
    }
}

impl Eq for BufferKey {
    fn eq(&self, other: &BufferKey) -> bool {
        let BufferKey(s) = *self;
        let BufferKey(o) = *other;
        s[0] == o[0] && s[1] == o[1]
    }
}

impl TotalEq for BufferKey {
    fn equals(&self, other: &BufferKey) -> bool {
        self.eq(other)
    }
}

/// Create a key from a given size
impl BufferKey {
    fn get(input: Size2D<uint>) -> BufferKey {
        BufferKey([input.width, input.height])
    }
}

/// A helper struct to keep track of buffers in the HashMap
struct BufferValue<T> {
    /// An array of buffers, all the same size
    buffers: ~[T],
    /// The counter when this size was last requested
    last_action: uint,
}

impl<T: Tile> BufferMap<T> {
    // Creates a new BufferMap with a given buffer limit.
    pub fn new(max_mem: uint) -> BufferMap<T> {
        BufferMap {
            map: HashMap::new(),
            mem: 0u,
            max_mem: max_mem,
            counter: 0u,
        }
    }

    /// Insert a new buffer into the map.
    pub fn insert(&mut self, graphics_context: &NativePaintingGraphicsContext, new_buffer: T) {
        let new_key = BufferKey::get(new_buffer.get_size_2d());

        // If all our buffers are the same size and we're already at our
        // memory limit, no need to store this new buffer; just let it drop.
        if self.mem + new_buffer.get_mem() > self.max_mem && self.map.len() == 1 &&
            self.map.contains_key(&new_key) {
            new_buffer.destroy(graphics_context);
            return;
        }

        self.mem += new_buffer.get_mem();
        // use lazy insertion function to prevent unnecessary allocation
        let counter = &self.counter;
        self.map.find_or_insert_with(new_key, |_| BufferValue {
            buffers: ~[],
            last_action: *counter
        }).buffers.push(new_buffer);

        let mut opt_key: Option<BufferKey> = None;
        while self.mem > self.max_mem {
            let old_key = match opt_key {
                Some(key) => key,
                None => {
                    match self.map.iter().min_by(|&(_, x)| x.last_action) {
                        Some((k, _)) => *k,
                        None => fail!("BufferMap: tried to delete with no elements in map"),
                    }
                }
            };
            if {
                let list = &mut self.map.get_mut(&old_key).buffers;
                let condemned_buffer = list.pop().take_unwrap();
                self.mem -= condemned_buffer.get_mem();
                condemned_buffer.destroy(graphics_context);
                list.is_empty()
            }
            { // then
                self.map.pop(&old_key); // Don't store empty vectors!
                opt_key = None;
            } else {
                opt_key = Some(old_key);
            }
        }
    }

    // Try to find a buffer for the given size.
    pub fn find(&mut self, size: Size2D<uint>) -> Option<T> {
        let mut flag = false; // True if key needs to be popped after retrieval.
        let key = BufferKey::get(size);
        let ret = match self.map.find_mut(&key) {
            Some(ref mut buffer_val) => {
                buffer_val.last_action = self.counter;
                self.counter += 1;

                let buffer = buffer_val.buffers.pop().take_unwrap();
                self.mem -= buffer.get_mem();
                if buffer_val.buffers.is_empty() {
                    flag = true;
                }
                Some(buffer)
            }
            None => None,
        };

        if flag {
            self.map.pop(&key); // Don't store empty vectors!
        }

        ret
    }

    /// Destroys all buffers.
    pub fn clear(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        let map = mem::replace(&mut self.map, HashMap::new());
        for (_, value) in map.move_iter() {
            for tile in value.buffers.move_iter() {
                tile.destroy(graphics_context)
            }
        }
        self.mem = 0
    }
}
<|endoftext|>


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

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

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

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

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

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

impl GlibPtrDefault for Atom {
    type GlibType = *mut ffi::GdkAtom;
}

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

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

impl FromGlibPtrNone<*mut ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::GdkAtom) -> Atom { Atom(*ptr) }
}

impl FromGlibPtrFull<*mut ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_full(_: *mut ffi::GdkAtom) -> Atom { unimplemented!() }
}

impl<'a> From<&'a str> for Atom {
    fn from(r: &'a str) -> Atom {
        skip_assert_initialized!();
        Atom::intern(r)
    }
}
<commit_msg>Add missing impls for Atom<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

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

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

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

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

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

impl GlibPtrDefault for Atom {
    type GlibType = *mut ffi::GdkAtom;
}

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

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

impl FromGlibPtrNone<*mut ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::GdkAtom) -> Atom { Atom(*ptr) }
}

impl FromGlibPtrFull<*mut ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_full(_: *mut ffi::GdkAtom) -> Atom { unimplemented!() }
}

impl FromGlibPtrNone<ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_none(ptr: ffi::GdkAtom) -> Atom { Atom(ptr) }
}

impl FromGlibPtrFull<ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_full(_: ffi::GdkAtom) -> Atom { unimplemented!() }
}

impl<'a> From<&'a str> for Atom {
    fn from(r: &'a str) -> Atom {
        skip_assert_initialized!();
        Atom::intern(r)
    }
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! Execution of a filter (predicate)

use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

use arrow::array::*;
use arrow::compute::array_ops::filter;
use arrow::datatypes::Schema;
use arrow::record_batch::RecordBatch;

use super::error::{ExecutionError, Result};
use super::expression::RuntimeExpr;
use super::relation::Relation;

pub struct FilterRelation {
    schema: Arc<Schema>,
    input: Rc<RefCell<Relation>>,
    expr: RuntimeExpr,
}

impl FilterRelation {
    pub fn new(
        input: Rc<RefCell<Relation>>,
        expr: RuntimeExpr,
        schema: Arc<Schema>,
    ) -> Self {
        Self {
            schema,
            input,
            expr,
        }
    }
}

impl Relation for FilterRelation {
    fn next(&mut self) -> Result<Option<RecordBatch>> {
        match self.input.borrow_mut().next()? {
            Some(batch) => {
                // evaluate the filter expression against the batch
                match self.expr.get_func()(&batch)?
                    .as_any()
                    .downcast_ref::<BooleanArray>()
                {
                    Some(filter_bools) => {
                        let filtered_columns: Result<Vec<ArrayRef>> = (0..batch
                            .num_columns())
                            .map(|i| {
                                match filter(batch.column(i).as_ref(), &filter_bools) {
                                    Ok(result) => Ok(result),
                                    Err(error) => Err(ExecutionError::from(error)),
                                }
                            })
                            .collect();

                        let filtered_batch: RecordBatch = RecordBatch::new(
                            Arc::new(Schema::empty()),
                            filtered_columns?,
                        );

                        Ok(Some(filtered_batch))
                    }
                    _ => Err(ExecutionError::ExecutionError(
                        "Filter expression did not evaluate to boolean".to_string(),
                    )),
                }
            }
            None => Ok(None),
        }
    }

    fn schema(&self) -> &Arc<Schema> {
        &self.schema
    }
}
<commit_msg>ARROW-4721: [Rust] [DataFusion] Propagate schema in filter<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! Execution of a filter (predicate)

use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

use arrow::array::*;
use arrow::compute::array_ops::filter;
use arrow::datatypes::Schema;
use arrow::record_batch::RecordBatch;

use super::error::{ExecutionError, Result};
use super::expression::RuntimeExpr;
use super::relation::Relation;

pub struct FilterRelation {
    schema: Arc<Schema>,
    input: Rc<RefCell<Relation>>,
    expr: RuntimeExpr,
}

impl FilterRelation {
    pub fn new(
        input: Rc<RefCell<Relation>>,
        expr: RuntimeExpr,
        schema: Arc<Schema>,
    ) -> Self {
        Self {
            schema,
            input,
            expr,
        }
    }
}

impl Relation for FilterRelation {
    fn next(&mut self) -> Result<Option<RecordBatch>> {
        match self.input.borrow_mut().next()? {
            Some(batch) => {
                // evaluate the filter expression against the batch
                match self.expr.get_func()(&batch)?
                    .as_any()
                    .downcast_ref::<BooleanArray>()
                {
                    Some(filter_bools) => {
                        let filtered_columns: Result<Vec<ArrayRef>> = (0..batch
                            .num_columns())
                            .map(|i| {
                                match filter(batch.column(i).as_ref(), &filter_bools) {
                                    Ok(result) => Ok(result),
                                    Err(error) => Err(ExecutionError::from(error)),
                                }
                            })
                            .collect();

                        let filtered_batch: RecordBatch =
                            RecordBatch::new(self.schema.clone(), filtered_columns?);

                        Ok(Some(filtered_batch))
                    }
                    _ => Err(ExecutionError::ExecutionError(
                        "Filter expression did not evaluate to boolean".to_string(),
                    )),
                }
            }
            None => Ok(None),
        }
    }

    fn schema(&self) -> &Arc<Schema> {
        &self.schema
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(mut self, b: bool) -> RefFlags {
        self.content_hashing = b;
        self
    }

    pub fn with_permission_tracking(mut self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        unimplemented!()
    }

    pub fn get_permission_tracking(&self) -> bool {
        unimplemented!()
    }

}

impl Into<Value> for RefFlags {

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    fn into(self) -> Value {
        let mut btm = BTreeMap::new();
        btm.insert(String::from("content_hashing"),     Value::Boolean(self.content_hashing));
        btm.insert(String::from("permission_tracking"), Value::Boolean(self.permission_tracking));
        return Value::Table(btm)
    }

}

<commit_msg>Impl RefFlags::with_permission_tracking()<commit_after>use std::collections::BTreeMap;

use toml::Value;

use error::RefErrorKind as REK;
use result::Result;

#[derive(Default)]
pub struct RefFlags {
    content_hashing:       bool,
    permission_tracking:   bool,
}

impl RefFlags {

    /// Read the RefFlags from a TOML document
    ///
    /// Assumes that the whole TOML tree is passed. So this looks up `ref.flags` to get the flags.
    /// It assumes that this is a Map with Key = <name of the setting> and Value = boolean.
    pub fn read(v: &Value) -> Result<RefFlags> {
        fn get_field(v: &Value, key: &str) -> Result<bool> {
            match v.lookup(key) {
                Some(&Value::Boolean(b)) => Ok(b),
                Some(_) => Err(REK::HeaderTypeError.into()),
                None    => Err(REK::HeaderFieldMissingError.into()),
            }
        }

        Ok(RefFlags {
            content_hashing:     try!(get_field(v, "ref.flags.content_hashing")),
            permission_tracking: try!(get_field(v, "ref.flags.permission_tracking")),
        })
    }

    /// Alias for `RefFlags::content_hashing()`
    pub fn is_often_moving(mut self, b: bool) -> RefFlags {
        self.with_content_hashing(b)
    }

    pub fn with_content_hashing(mut self, b: bool) -> RefFlags {
        self.content_hashing = b;
        self
    }

    pub fn with_permission_tracking(self, b: bool) -> RefFlags {
        self.permission_tracking = b;
        self
    }

    pub fn get_content_hashing(&self) -> bool {
        unimplemented!()
    }

    pub fn get_permission_tracking(&self) -> bool {
        unimplemented!()
    }

}

impl Into<Value> for RefFlags {

    /// Build a TOML::Value from this RefFlags object.
    ///
    /// Returns a Map which should be set in `ref.flags` in the header.
    fn into(self) -> Value {
        let mut btm = BTreeMap::new();
        btm.insert(String::from("content_hashing"),     Value::Boolean(self.content_hashing));
        btm.insert(String::from("permission_tracking"), Value::Boolean(self.permission_tracking));
        return Value::Table(btm)
    }

}

<|endoftext|>


<commit_before>use std::path::Path;
use std::process::Command;

fn main() {

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    // https://github.com/bitcoin/bitcoin/issues/7714
    // println!("cargo:rustc-link-lib=Qt");
    // HACK - missing pkgconfig files in Qt5.6
    // QT_CFLAGS="-I${QTDIR}/include -I${QTDIR}/include/QtWidgets -I${QTDIR}/include/QtCore \
    //            -I${QTDIR}/include/QtGui -I${QTDIR}/include/QtNetwork"
    // QT_LIBS="-F${QTDIR}/lib -framework QtCore -framework QtNetwork -framework QtGui -framework QtWidgets" ./configure --with-gui=qt5
    // QT_LIBS="-F${QTDIR}/lib -framework QtCore -framework QtNetwork -framework QtGui -framework QtWidgets"
    // let qtdir = String::from("/Users/nicolas/Qt/5.6/clang_64/lib");
    let qtdir = String::from("/Users/nicolas/Qt/5.7/clang_64/lib");

    println!("cargo:rustc-link-search=framework={}", qtdir);
    // println!("cargo:rustc-flags=-L framework={}", qtdir);

    println!("cargo:rustc-link-lib=framework=QtCore");
    println!("cargo:rustc-link-lib=framework=QtNetwork");
    println!("cargo:rustc-link-lib=framework=QtGui");
    println!("cargo:rustc-link-lib=framework=QtQml");
    println!("cargo:rustc-link-lib=framework=QtWidgets");

    println!("cargo:rustc-flags=-l stdc++");

}
<commit_msg>libqmlbind-sys: Cleanup and fix build.rs<commit_after>use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();

    // Initialize git submodule
    if !Path::new("libqmlbind/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    Command::new("qmake").current_dir("libqmlbind").output().unwrap();
    Command::new("make").current_dir("libqmlbind").output().unwrap();
    Command::new("make").arg("staticlib").current_dir("libqmlbind/qmlbind").output().unwrap();

    println!("cargo:rustc-flags=-L libqmlbind/qmlbind");
    println!("cargo:rustc-link-lib=static=qmlbind");
    // println!("cargo:rustc-link-lib=qmlbind");

    let qt_dir = env::var("QT_DIR").map(|p| PathBuf::from(p)).unwrap_or({
        println!("Environnement variable 'QT_DIR' not set!");
        println!("Defaulting to ${{HOME}}/Qt/${{QT_VER}}/${{QT_COMP}} where:");
        let home_dir = env::home_dir().map(|p| PathBuf::from(p)).unwrap();
        let default_qt_ver = "5.7".to_string();
        let default_qt_comp = if target.contains("linux") {
            "gcc_64".to_string()
        } else if target.contains("darwin") {
            "clang_64".to_string()
        } else {
            panic!("Unsuported platform in gallery's build.rs!")
        };
        println!("    QT_VER:  {}", default_qt_ver);
        println!("    QT_COMP: {}", default_qt_comp);
        let qt_dir_default = home_dir.join("Qt")
                                  .join(env::var("QT_VER").unwrap_or(default_qt_ver))
                                  .join(env::var("QT_COMP").unwrap_or(default_qt_comp));
        qt_dir_default
    });
    println!("Using Qt directory: {:?}", qt_dir);
    println!("Use QT_DIR environment variable to ovewrite.");

    let qt_lib_dir = qt_dir.join("lib").to_str().unwrap().to_string();

    let osx_framework = if target.contains("darwin") { "=framework" }
                        else  { "" };

    println!("cargo:rustc-link-search{}={}", osx_framework, qt_lib_dir);

    println!("cargo:rustc-link-lib{}=QtCore", osx_framework);
    println!("cargo:rustc-link-lib{}=QtNetwork", osx_framework);
    println!("cargo:rustc-link-lib{}=QtGui", osx_framework);
    println!("cargo:rustc-link-lib{}=QtQml", osx_framework);
    println!("cargo:rustc-link-lib{}=QtWidgets", osx_framework);

    println!("cargo:rustc-flags=-l stdc++");
}
<|endoftext|>


<commit_before>//! Untagged serialization/deserialization support for Option<Either<L, R>>.
//!
//! `Either` uses default, externally-tagged representation.
//! However, sometimes it is useful to support several alternative types.
//! For example, we may have a field which is generally Map<String, i32>
//! but in typical cases Vec<String> would suffice, too.
//! ```rust
//! #[macro_use]
//! extern crate serde;
//! // or `use serde::{Serialize, Deserialize};` in newer rust versions.
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use std::collections::HashMap;
//!
//! #[derive(Serialize, Deserialize, Debug)]
//! #[serde(transparent)]
//! struct IntOrString {
//!     #[serde(with="either::serde_untagged")]
//!     inner: either::Either<Vec<String>, HashMap<String, i32>>
//! };
//! // serialization
//! let data = IntOrString {
//!     inner: either::Either::Left(vec!["Hello".to_string()])
//! };
//! // notice: no tags are emitted.
//! assert_eq!(serde_json::to_string(&data)?, r#"["Hello"]"#);
//! // deserialization
//! let data: IntOrString = serde_json::from_str(
//!     r#"{"a": 0, "b": 14}"#
//! )?;
//! println!("found {:?}", data);
//! # Ok(())
//! }
//! ```

use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Either<L, R> {
    Left(L),
    Right(R),
}

pub fn serialize<L, R, S>(
    this: &Option<super::Either<L, R>>,
    serializer: S,
) -> Result<S::Ok, S::Error>
where
    S: Serializer,
    L: Serialize,
    R: Serialize,
{
    let untagged = this
        .as_ref()
        .map(|either| either.as_ref().either(Either::Left, Either::Right));
    untagged.serialize(serializer)
}

pub fn deserialize<'de, L, R, D>(deserializer: D) -> Result<Option<super::Either<L, R>>, D::Error>
where
    D: Deserializer<'de>,
    L: Deserialize<'de>,
    R: Deserialize<'de>,
{
    let untagged = try!(Option::<Either<L, R>>::deserialize(deserializer));
    match untagged {
        None => Ok(None),
        Some(Either::Left(left)) => Ok(Some(super::Either::Left(left))),
        Some(Either::Right(right)) => Ok(Some(super::Either::Right(right))),
    }
}
<commit_msg>fix doctest<commit_after>//! Untagged serialization/deserialization support for Option<Either<L, R>>.
//!
//! `Either` uses default, externally-tagged representation.
//! However, sometimes it is useful to support several alternative types.
//! For example, we may have a field which is generally Map<String, i32>
//! but in typical cases Vec<String> would suffice, too.
//! ```rust
//! #[macro_use]
//! extern crate serde;
//! // or `use serde::{Serialize, Deserialize};` in newer rust versions.
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use std::collections::HashMap;
//!
//! #[derive(Serialize, Deserialize, Debug)]
//! #[serde(transparent)]
//! struct IntOrString {
//!     #[serde(with="either::serde_untagged_optional")]
//!     inner: Option<either::Either<Vec<String>, HashMap<String, i32>>>
//! };
//! // serialization
//! let data = IntOrString {
//!     inner: Some(either::Either::Left(vec!["Hello".to_string()]))
//! };
//! // notice: no tags are emitted.
//! assert_eq!(serde_json::to_string(&data)?, r#"["Hello"]"#);
//! // deserialization
//! let data: IntOrString = serde_json::from_str(
//!     r#"{"a": 0, "b": 14}"#
//! )?;
//! println!("found {:?}", data);
//! # Ok(())
//! }
//! ```

use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Either<L, R> {
    Left(L),
    Right(R),
}

pub fn serialize<L, R, S>(
    this: &Option<super::Either<L, R>>,
    serializer: S,
) -> Result<S::Ok, S::Error>
where
    S: Serializer,
    L: Serialize,
    R: Serialize,
{
    let untagged = this
        .as_ref()
        .map(|either| either.as_ref().either(Either::Left, Either::Right));
    untagged.serialize(serializer)
}

pub fn deserialize<'de, L, R, D>(deserializer: D) -> Result<Option<super::Either<L, R>>, D::Error>
where
    D: Deserializer<'de>,
    L: Deserialize<'de>,
    R: Deserialize<'de>,
{
    let untagged = try!(Option::<Either<L, R>>::deserialize(deserializer));
    match untagged {
        None => Ok(None),
        Some(Either::Left(left)) => Ok(Some(super::Either::Left(left))),
        Some(Either::Right(right)) => Ok(Some(super::Either::Right(right))),
    }
}
<|endoftext|>


<commit_before>use serde_json;

// TODO: use when new version drops
//use serialport::{SerialPortInfo,UsbPortInfo,SerialPortType};

use std::fmt;
use std::sync::mpsc::Sender;

#[derive( Clone, Debug)]
pub struct SubscriptionRequest {
  pub sub_id: String,
  pub subscriber: Sender<SerialResponse>,
}

/// Represents the valid json requests that can be made
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SerialRequest {
  // TODO: Divorce subscriptions from port open/close?
  // Right now port is only closed when last subscriber
  // unsubscribes
  /// Open a port for reading
  Open { sub_id: String, port: String },
  /// Take control of a port for writing
  WriteLock { sub_id: String, port: String },
  /// Release control of a port for writing
  /// If no port is given, release all write locks
  /// for all ports
  ReleaseWriteLock {
    sub_id: String,
    port: Option<String>,
  },
  /// Write data, only works if we have control
  Write {
    sub_id: String,
    port: String,
    data: String,
    base64: Option<bool>,
  },
  /// Close a port
  Close {
    sub_id: String,
    port: Option<String>,
  },
  /// List serial ports
  List { sub_id: String },
}

impl fmt::Display for SerialRequest {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let json = serde_json::to_string(self).unwrap_or("Display SerialRequest: Serialization Failed!"
                                                       .to_string());
    write!(f, "{}", json)
  }
}

/// Represents the valid serial responses that can be made
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SerialResponse {
  /// Error response
  Error {
    description: String,
    display: String,
  },
  /// Data that was read from port
  Read {
    port: String,
    data: String,
    base64: Option<bool>,
  },
  /// Port was closed
  Closed { port: String },
  /// Port was closed
  Opened { port: String },
  /// Command successful
  Ok { msg: String },
  /// List serial ports response
  List { ports: Vec<String> },
}

/*
// TODO: Uncomment when new serialport module version drops
/// Needed for Serde Support as
/// SerialPortInfo is in seperate module
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(remote = "SerialPortInfo")]
pub struct SerialPortInfoDef {
    /// The short name of the serial port
    pub port_name: String,
    /// The hardware device type that exposes this port
    pub port_type: SerialPortType,

}

#[derive(Serialize, Deserialize)]
#[serde(remote = "sp::SerialPortType")]
/// The physical type of a `SerialPort`
pub enum SerialPortTypeDef {
    /// The serial port is connected via USB
    UsbPort(UsbPortInfoDef),
    /// The serial port is connected via PCI (permanent port)
    PciPort,
    /// The serial port is connected via Bluetooth
    BluetoothPort,
    /// It can't be determined how the serial port is connected
    Unknown,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "UsbPortInfo")]
pub struct UsbPortInfoDef {
    /// Vender ID
    pub vid: u16,
    /// Product ID
    pub pid: u16,
    /// Serial number (arbitrary string)
    pub serial_number: Option<String>,
    /// Manufacturer (arbitrary string)
    pub manufacturer: Option<String>,
    /// Product name (arbitrary string)
    pub product: Option<String>,
}
*/

impl fmt::Display for SerialResponse {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let json = serde_json::to_string(self).unwrap_or("Display SerialResponse: Serialization Failed!"
                                                       .to_string());
    write!(f, "{}", json)
  }
}
<commit_msg>Clarify close request<commit_after>use serde_json;

// TODO: use when new version drops
//use serialport::{SerialPortInfo,UsbPortInfo,SerialPortType};

use std::fmt;
use std::sync::mpsc::Sender;

#[derive( Clone, Debug)]
pub struct SubscriptionRequest {
  pub sub_id: String,
  pub subscriber: Sender<SerialResponse>,
}

/// Represents the valid json requests that can be made
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SerialRequest {
  // TODO: Divorce subscriptions from port open/close?
  // Right now port is only closed when last subscriber
  // unsubscribes
  /// Open a port for reading
  Open { sub_id: String, port: String },
  /// Take control of a port for writing
  WriteLock { sub_id: String, port: String },
  /// Release control of a port for writing
  /// If no port is given, release all write locks
  /// for all ports
  ReleaseWriteLock {
    sub_id: String,
    port: Option<String>,
  },
  /// Write data, only works if we have control
  Write {
    sub_id: String,
    port: String,
    data: String,
    base64: Option<bool>,
  },
  /// Close a port or subscription
  Close {
    sub_id: String,
    port: Option<String>,
  },
  /// List serial ports
  List { sub_id: String },
}

impl fmt::Display for SerialRequest {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let json = serde_json::to_string(self).unwrap_or("Display SerialRequest: Serialization Failed!"
                                                       .to_string());
    write!(f, "{}", json)
  }
}

/// Represents the valid serial responses that can be made
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SerialResponse {
  /// Error response
  Error {
    description: String,
    display: String,
  },
  /// Data that was read from port
  Read {
    port: String,
    data: String,
    base64: Option<bool>,
  },
  /// Port was closed
  Closed { port: String },
  /// Port was closed
  Opened { port: String },
  /// Command successful
  Ok { msg: String },
  /// List serial ports response
  List { ports: Vec<String> },
}

/*
// TODO: Uncomment when new serialport module version drops
/// Needed for Serde Support as
/// SerialPortInfo is in seperate module
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(remote = "SerialPortInfo")]
pub struct SerialPortInfoDef {
    /// The short name of the serial port
    pub port_name: String,
    /// The hardware device type that exposes this port
    pub port_type: SerialPortType,

}

#[derive(Serialize, Deserialize)]
#[serde(remote = "sp::SerialPortType")]
/// The physical type of a `SerialPort`
pub enum SerialPortTypeDef {
    /// The serial port is connected via USB
    UsbPort(UsbPortInfoDef),
    /// The serial port is connected via PCI (permanent port)
    PciPort,
    /// The serial port is connected via Bluetooth
    BluetoothPort,
    /// It can't be determined how the serial port is connected
    Unknown,
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "UsbPortInfo")]
pub struct UsbPortInfoDef {
    /// Vender ID
    pub vid: u16,
    /// Product ID
    pub pid: u16,
    /// Serial number (arbitrary string)
    pub serial_number: Option<String>,
    /// Manufacturer (arbitrary string)
    pub manufacturer: Option<String>,
    /// Product name (arbitrary string)
    pub product: Option<String>,
}
*/

impl fmt::Display for SerialResponse {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let json = serde_json::to_string(self).unwrap_or("Display SerialResponse: Serialization Failed!"
                                                       .to_string());
    write!(f, "{}", json)
  }
}
<|endoftext|>


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

//! Post chat messages to Slack.
//!
//! For more information, see [Slack's API
//! documentation](https://api.slack.com/methods).

use std::collections::HashMap;

use super::{ApiResult, SlackWebRequestSender, parse_slack_response};

/// Deletes a message.
///
/// Wraps https://api.slack.com/methods/chat.delete
pub fn delete<R: SlackWebRequestSender>(client: &R, token: &str, ts: &str, channel: &str) -> ApiResult<DeleteResponse> {
    let mut params = HashMap::new();
    params.insert("ts", ts);
    params.insert("channel", channel);
    let response = try!(client.send_authed("chat.delete", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct DeleteResponse {
    pub channel: String,
    pub ts: String,
}

/// Sends a message to a channel.
///
/// Wraps https://api.slack.com/methods/chat.postMessage
pub fn post_message<R: SlackWebRequestSender>(client: &R,
                    token: &str,
                    channel: &str,
                    text: &str,
                    username: Option<&str>,
                    as_user: Option<bool>,
                    parse: Option<&str>,
                    link_names: Option<bool>,
                    attachments: Option<&str>,
                    unfurl_links: Option<bool>,
                    unfurl_media: Option<bool>,
                    icon_url: Option<&str>,
                    icon_emoji: Option<&str>)
                    -> ApiResult<PostMessageResponse> {
    let mut params = HashMap::new();
    params.insert("channel", channel);
    params.insert("text", text);
    if let Some(username) = username {
        params.insert("username", username);
    }
    if let Some(as_user) = as_user {
        params.insert("as_user",
                      if as_user {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(parse) = parse {
        params.insert("parse", parse);
    }
    if let Some(link_names) = link_names {
        params.insert("link_names",
                      if link_names {
                          "1"
                      } else {
                          "0"
                      });
    }
    if let Some(attachments) = attachments {
        params.insert("attachments", attachments);
    }
    if let Some(unfurl_links) = unfurl_links {
        params.insert("unfurl_links",
                      if unfurl_links {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(unfurl_media) = unfurl_media {
        params.insert("unfurl_media",
                      if unfurl_media {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(icon_url) = icon_url {
        params.insert("icon_url", icon_url);
    }
    if let Some(icon_emoji) = icon_emoji {
        params.insert("icon_emoji", icon_emoji);
    }
    let response = try!(client.send_authed("chat.postMessage", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct PostMessageResponse {
    pub ts: String,
    pub channel: String,
    pub message: super::Message,
}

/// Updates a message.
///
/// Wraps https://api.slack.com/methods/chat.update
pub fn update<R: SlackWebRequestSender>(client: &R,
              token: &str,
              ts: &str,
              channel: &str,
              text: &str,
              attachments: Option<&str>,
              parse: Option<&str>,
              link_names: Option<bool>)
              -> ApiResult<UpdateResponse> {
    let mut params = HashMap::new();
    params.insert("ts", ts);
    params.insert("channel", channel);
    params.insert("text", text);
    if let Some(attachments) = attachments {
        params.insert("attachments", attachments);
    }
    if let Some(parse) = parse {
        params.insert("parse", parse);
    }
    if let Some(link_names) = link_names {
        params.insert("link_names",
                      if link_names {
                          "1"
                      } else {
                          "0"
                      });
    }
    let response = try!(client.send_authed("chat.update", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct UpdateResponse {
    pub channel: String,
    pub ts: String,
    pub text: String,
}

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

    #[test]
    fn general_api_error_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{"ok": false, "err": "some_error"}"#);
        let result = post_message(&client,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        assert!(result.is_err());
    }

    #[test]
    fn delete_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "channel": "C024BE91L",
            "ts": "1401383885.000061"
        }"#);
        let result = delete(&client, "TEST_TOKEN", "TEST_CHANNEL", "1401383885.000061");
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        assert_eq!(result.unwrap().ts, "1401383885.000061");
    }

    #[test]
    fn post_message_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "ts": "1405895017.000506",
            "channel": "C024BE91L",
            "message": {
                "type": "message",
                "user": "U024BE7LH",
                "text": "Test message",
                "ts": "1444078138.000084"
            }
        }"#);
        let result = post_message(&client,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  Some(true),
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        match result.unwrap().message {
            Message::Standard { ts: _, channel: _, user: _, text, is_starred: _, pinned_to: _, reactions: _, edited: _, attachments: _ } => {
                assert_eq!(text.unwrap(), "Test message");
            }
            _ => panic!("Message decoded into incorrect variant."),
        }
    }

    #[test]
    fn bot_post_message_ok_response() {
        let sender = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "ts": "1405895017.000506",
            "channel": "C024BE91L",
            "message": {
                "type": "message",
                "text": "Test message",
                "ts": "1444078138.000084"
            }
        }"#);
        let result = post_message(&sender,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        match result.unwrap().message.clone() {
            Message::Standard { ts: _, channel: _, user: _, text, is_starred: _, pinned_to: _, reactions: _, edited: _, attachments: _ } => {
                assert_eq!(text.unwrap(), "Test message")
            }
            _ => panic!("Message decoded into incorrect variant."),
        }
    }

    #[test]
    fn update_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "channel": "C024BE91L",
            "ts": "1401383885.000061",
            "text": "Test message"
        }"#);
        let result = update(&client,
                            "TEST_TOKEN",
                            "TEST_CHANNEL",
                            "1401383885.000061",
                            "Test message",
                            None,
                            None,
                            None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        assert_eq!(result.unwrap().text, "Test message");
    }
}
<commit_msg>Update chat.rs (#32)<commit_after>// Copyright 2015-2016 the slack-rs authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Post chat messages to Slack.
//!
//! For more information, see [Slack's API
//! documentation](https://api.slack.com/methods).

use std::collections::HashMap;

use super::{ApiResult, SlackWebRequestSender, parse_slack_response};

/// Deletes a message.
///
/// Wraps https://api.slack.com/methods/chat.delete
pub fn delete<R: SlackWebRequestSender>(client: &R, token: &str, ts: &str, channel: &str) -> ApiResult<DeleteResponse> {
    let mut params = HashMap::new();
    params.insert("ts", ts);
    params.insert("channel", channel);
    let response = try!(client.send_authed("chat.delete", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct DeleteResponse {
    pub channel: String,
    pub ts: String,
}

/// Sends a message to a channel.
///
/// Wraps https://api.slack.com/methods/chat.postMessage
pub fn post_message<R: SlackWebRequestSender>(client: &R,
                    token: &str,
                    channel: &str,
                    text: &str,
                    username: Option<&str>,
                    as_user: Option<bool>,
                    parse: Option<&str>,
                    link_names: Option<bool>,
                    attachments: Option<&str>,
                    unfurl_links: Option<bool>,
                    unfurl_media: Option<bool>,
                    icon_url: Option<&str>,
                    icon_emoji: Option<&str>)
                    -> ApiResult<PostMessageResponse> {
    let mut params = HashMap::new();
    params.insert("channel", channel);
    params.insert("text", text);
    if let Some(username) = username {
        params.insert("username", username);
    }
    if let Some(as_user) = as_user {
        params.insert("as_user",
                      if as_user {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(parse) = parse {
        params.insert("parse", parse);
    }
    if let Some(link_names) = link_names {
        params.insert("link_names",
                      if link_names {
                          "1"
                      } else {
                          "0"
                      });
    }
    if let Some(attachments) = attachments {
        params.insert("attachments", attachments);
    }
    if let Some(unfurl_links) = unfurl_links {
        params.insert("unfurl_links",
                      if unfurl_links {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(unfurl_media) = unfurl_media {
        params.insert("unfurl_media",
                      if unfurl_media {
                          "true"
                      } else {
                          "false"
                      });
    }
    if let Some(icon_url) = icon_url {
        params.insert("icon_url", icon_url);
    }
    if let Some(icon_emoji) = icon_emoji {
        params.insert("icon_emoji", icon_emoji);
    }
    let response = try!(client.send_authed("chat.postMessage", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct PostMessageResponse {
    pub ts: String,
    pub channel: String,
    pub message: super::Message,
}

/// Updates a message.
///
/// Wraps https://api.slack.com/methods/chat.update
pub fn update<R: SlackWebRequestSender>(client: &R,
              token: &str,
              ts: &str,
              channel: &str,
              text: &str,
              attachments: Option<&str>,
              parse: Option<&str>,
              link_names: Option<bool>)
              -> ApiResult<UpdateResponse> {
    let mut params = HashMap::new();
    params.insert("ts", ts);
    params.insert("channel", channel);
    params.insert("text", text);
    if let Some(attachments) = attachments {
        params.insert("attachments", attachments);
    }
    if let Some(parse) = parse {
        params.insert("parse", parse);
    }
    if let Some(link_names) = link_names {
        params.insert("link_names",
                      if link_names {
                          "1"
                      } else {
                          "0"
                      });
    }
    let response = try!(client.send_authed("chat.update", token, params));
    parse_slack_response(response, true)
}

#[derive(Clone,Debug,RustcDecodable)]
pub struct UpdateResponse {
    pub channel: String,
    pub ts: String,
    pub text: String,
}

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

    #[test]
    fn general_api_error_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{"ok": false, "err": "some_error"}"#);
        let result = post_message(&client,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        assert!(result.is_err());
    }

    #[test]
    fn delete_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "channel": "C024BE91L",
            "ts": "1401383885.000061"
        }"#);
        let result = delete(&client, "TEST_TOKEN", "1401383885.000061", "C024BE91L");
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        assert_eq!(result.unwrap().ts, "1401383885.000061");
    }

    #[test]
    fn post_message_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "ts": "1405895017.000506",
            "channel": "C024BE91L",
            "message": {
                "type": "message",
                "user": "U024BE7LH",
                "text": "Test message",
                "ts": "1444078138.000084"
            }
        }"#);
        let result = post_message(&client,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  Some(true),
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        match result.unwrap().message {
            Message::Standard { ts: _, channel: _, user: _, text, is_starred: _, pinned_to: _, reactions: _, edited: _, attachments: _ } => {
                assert_eq!(text.unwrap(), "Test message");
            }
            _ => panic!("Message decoded into incorrect variant."),
        }
    }

    #[test]
    fn bot_post_message_ok_response() {
        let sender = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "ts": "1405895017.000506",
            "channel": "C024BE91L",
            "message": {
                "type": "message",
                "text": "Test message",
                "ts": "1444078138.000084"
            }
        }"#);
        let result = post_message(&sender,
                                  "TEST_TOKEN",
                                  "TEST_CHANNEL",
                                  "Test message",
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        match result.unwrap().message.clone() {
            Message::Standard { ts: _, channel: _, user: _, text, is_starred: _, pinned_to: _, reactions: _, edited: _, attachments: _ } => {
                assert_eq!(text.unwrap(), "Test message")
            }
            _ => panic!("Message decoded into incorrect variant."),
        }
    }

    #[test]
    fn update_ok_response() {
        let client = MockSlackWebRequestSender::respond_with(r#"{
            "ok": true,
            "channel": "C024BE91L",
            "ts": "1401383885.000061",
            "text": "Test message"
        }"#);
        let result = update(&client,
                            "TEST_TOKEN",
                            "TEST_CHANNEL",
                            "1401383885.000061",
                            "Test message",
                            None,
                            None,
                            None);
        if let Err(err) = result {
            panic!(format!("{:?}", err));
        }
        assert_eq!(result.unwrap().text, "Test message");
    }
}
<|endoftext|>


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

use std::fs::File;
use std::path::{Path, PathBuf};

use api::{CaptureBits, ExternalImageData, ImageDescriptor};
use api::units::TexelRect;
#[cfg(feature = "png")]
use api::units::DeviceIntSize;
#[cfg(feature = "png")]
use device::ReadPixelsFormat;
#[cfg(feature = "capture")]
use print_tree::{PrintableTree, PrintTree};
use ron;
use serde;

#[derive(Clone)]
pub struct CaptureConfig {
    pub root: PathBuf,
    pub bits: CaptureBits,
    #[cfg(feature = "capture")]
    pretty: ron::ser::PrettyConfig,
}

impl CaptureConfig {
    #[cfg(feature = "capture")]
    pub fn new(root: PathBuf, bits: CaptureBits) -> Self {
        CaptureConfig {
            root,
            bits,
            #[cfg(feature = "capture")]
            pretty: ron::ser::PrettyConfig {
                enumerate_arrays: true,
                .. ron::ser::PrettyConfig::default()
            },
        }
    }

    pub fn file_path<P>(&self, name: P, ext: &str) -> PathBuf
    where P: AsRef<Path> {
        self.root.join(name).with_extension(ext)
    }

    #[cfg(feature = "capture")]
    pub fn serialize<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        use std::io::Write;

        let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
            .unwrap();
        let path = self.file_path(name, "ron");
        let mut file = File::create(path)
            .unwrap();
        write!(file, "{}\n", ron)
            .unwrap();
    }

    #[cfg(feature = "capture")]
    pub fn serialize_tree<T, P>(&self, data: &T, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        let path = self.root
            .join(name)
            .with_extension("tree");
        let file = File::create(path)
            .unwrap();
        let mut pt = PrintTree::new_with_sink("", file);
        data.print_with(&mut pt);
    }

    #[cfg(feature = "replay")]
    pub fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        use std::io::Read;

        let mut string = String::new();
        let path = root
            .join(name.as_ref())
            .with_extension("ron");
        File::open(path)
            .ok()?
            .read_to_string(&mut string)
            .unwrap();
        match ron::de::from_str(&string) {
            Ok(out) => Some(out),
            Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
        }
    }

    #[cfg(feature = "png")]
    pub fn save_png(
        path: PathBuf, size: DeviceIntSize, format: ReadPixelsFormat, data: &[u8],
    ) {
        use api::ImageFormat;
        use png::{BitDepth, ColorType, Encoder, HasParameters};
        use std::io::BufWriter;

        let color_type = match format {
            ReadPixelsFormat::Rgba8 => ColorType::RGBA,
            ReadPixelsFormat::Standard(ImageFormat::BGRA8) => {
                warn!("Unable to swizzle PNG of BGRA8 type");
                ColorType::RGBA
            },
            ReadPixelsFormat::Standard(ImageFormat::R8) => ColorType::Grayscale,
            ReadPixelsFormat::Standard(ImageFormat::RG8) => ColorType::GrayscaleAlpha,
            ReadPixelsFormat::Standard(fm) => {
                error!("Unable to save PNG of {:?}", fm);
                return;
            }
        };
        let w = BufWriter::new(File::create(path).unwrap());
        let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
        enc
            .set(color_type)
            .set(BitDepth::Eight);
        enc
            .write_header()
            .unwrap()
            .write_image_data(&data)
            .unwrap();
    }
}

/// An image that `ResourceCache` is unable to resolve during a capture.
/// The image has to be transferred to `Renderer` and locked with the
/// external image handler to get the actual contents and serialize them.
#[derive(Deserialize, Serialize)]
pub struct ExternalCaptureImage {
    pub short_path: String,
    pub descriptor: ImageDescriptor,
    pub external: ExternalImageData,
}

/// A short description of an external image to be saved separately as
/// "externals/XX.ron", redirecting into a specific texture/blob with
/// the corresponding UV rectangle.
#[derive(Deserialize, Serialize)]
pub struct PlainExternalImage {
    /// Path to the RON file describing the texel data.
    pub data: String,
    /// External image data source.
    pub external: ExternalImageData,
    /// UV sub-rectangle of the image.
    pub uv: TexelRect,
}
<commit_msg>Bug 1547290 - Mark CaptureConfig::file_path allow(dead_code) on a CLOSED TREE. r=me<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fs::File;
use std::path::{Path, PathBuf};

use api::{CaptureBits, ExternalImageData, ImageDescriptor};
use api::units::TexelRect;
#[cfg(feature = "png")]
use api::units::DeviceIntSize;
#[cfg(feature = "png")]
use device::ReadPixelsFormat;
#[cfg(feature = "capture")]
use print_tree::{PrintableTree, PrintTree};
use ron;
use serde;

#[derive(Clone)]
pub struct CaptureConfig {
    pub root: PathBuf,
    pub bits: CaptureBits,
    #[cfg(feature = "capture")]
    pretty: ron::ser::PrettyConfig,
}

impl CaptureConfig {
    #[cfg(feature = "capture")]
    pub fn new(root: PathBuf, bits: CaptureBits) -> Self {
        CaptureConfig {
            root,
            bits,
            #[cfg(feature = "capture")]
            pretty: ron::ser::PrettyConfig {
                enumerate_arrays: true,
                .. ron::ser::PrettyConfig::default()
            },
        }
    }

    #[cfg(feature = "capture")]
    pub fn file_path<P>(&self, name: P, ext: &str) -> PathBuf
    where P: AsRef<Path> {
        self.root.join(name).with_extension(ext)
    }

    #[cfg(feature = "capture")]
    pub fn serialize<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        use std::io::Write;

        let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
            .unwrap();
        let path = self.file_path(name, "ron");
        let mut file = File::create(path)
            .unwrap();
        write!(file, "{}\n", ron)
            .unwrap();
    }

    #[cfg(feature = "capture")]
    pub fn serialize_tree<T, P>(&self, data: &T, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        let path = self.root
            .join(name)
            .with_extension("tree");
        let file = File::create(path)
            .unwrap();
        let mut pt = PrintTree::new_with_sink("", file);
        data.print_with(&mut pt);
    }

    #[cfg(feature = "replay")]
    pub fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        use std::io::Read;

        let mut string = String::new();
        let path = root
            .join(name.as_ref())
            .with_extension("ron");
        File::open(path)
            .ok()?
            .read_to_string(&mut string)
            .unwrap();
        match ron::de::from_str(&string) {
            Ok(out) => Some(out),
            Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
        }
    }

    #[cfg(feature = "png")]
    pub fn save_png(
        path: PathBuf, size: DeviceIntSize, format: ReadPixelsFormat, data: &[u8],
    ) {
        use api::ImageFormat;
        use png::{BitDepth, ColorType, Encoder, HasParameters};
        use std::io::BufWriter;

        let color_type = match format {
            ReadPixelsFormat::Rgba8 => ColorType::RGBA,
            ReadPixelsFormat::Standard(ImageFormat::BGRA8) => {
                warn!("Unable to swizzle PNG of BGRA8 type");
                ColorType::RGBA
            },
            ReadPixelsFormat::Standard(ImageFormat::R8) => ColorType::Grayscale,
            ReadPixelsFormat::Standard(ImageFormat::RG8) => ColorType::GrayscaleAlpha,
            ReadPixelsFormat::Standard(fm) => {
                error!("Unable to save PNG of {:?}", fm);
                return;
            }
        };
        let w = BufWriter::new(File::create(path).unwrap());
        let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
        enc
            .set(color_type)
            .set(BitDepth::Eight);
        enc
            .write_header()
            .unwrap()
            .write_image_data(&data)
            .unwrap();
    }
}

/// An image that `ResourceCache` is unable to resolve during a capture.
/// The image has to be transferred to `Renderer` and locked with the
/// external image handler to get the actual contents and serialize them.
#[derive(Deserialize, Serialize)]
pub struct ExternalCaptureImage {
    pub short_path: String,
    pub descriptor: ImageDescriptor,
    pub external: ExternalImageData,
}

/// A short description of an external image to be saved separately as
/// "externals/XX.ron", redirecting into a specific texture/blob with
/// the corresponding UV rectangle.
#[derive(Deserialize, Serialize)]
pub struct PlainExternalImage {
    /// Path to the RON file describing the texel data.
    pub data: String,
    /// External image data source.
    pub external: ExternalImageData,
    /// UV sub-rectangle of the image.
    pub uv: TexelRect,
}
<|endoftext|>