<commit_before>use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;
use std::str::CharRange;

pub struct TokenValue {
    token: Token,
    value: ~str
}

impl TokenValue {
    pub fn new(tok: Token, val: ~str) -> TokenValue {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

struct LexerIterator<'a> {
    string: &'a str,
    pos: uint,
    line: uint,
    next: uint,
    current: Option<char>,
    peek: Option<char>,
    previous: Option<char>
}

impl<'a> LexerIterator<'a> {
    pub fn new(string: &'a str) -> LexerIterator<'a> {
        LexerIterator {
            string: string,
            pos: 0,
            next: 0,
            line: 1,
            current: None,
            peek: None,
            previous: None
        }
    }

    pub fn next(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.pos = next;

            if self.current.is_some() {
                self.previous = self.current;
            }

            self.current = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.peek = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut LexerIterator<'a>,
    done: bool
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            iter: unsafe { transmute(~LexerIterator::new(input)) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue> {
        unsafe {
            for c in *self.iter {
                match c {
                    ' ' => continue,
                    '\r' => continue,
                    '\n' => {
                        (*self.iter).line += 1;
                        continue
                    },
                    '(' => return Some(TokenValue::new(LPAREN, ~"(")),
                    ')' => return Some(TokenValue::new(RPAREN, ~")")),
                    '+' => return Some(TokenValue::new(PLUS, ~"+")),
                    '-' => return Some(TokenValue::new(MINUS, ~"-")),
                    ':' => return Some(TokenValue::new(COLON, ~":")),
                    '9' => return Some(TokenValue::new(INTEGER, ~"9")),
                    '8' => return Some(TokenValue::new(INTEGER, ~"8")),
                    '7' => return Some(TokenValue::new(INTEGER, ~"7")),
                    '6' => return Some(TokenValue::new(INTEGER, ~"6")),
                    '5' => return Some(TokenValue::new(INTEGER, ~"5")),
                    '4' => return Some(TokenValue::new(INTEGER, ~"4")),
                    '3' => return Some(TokenValue::new(INTEGER, ~"3")),
                    '2' => return Some(TokenValue::new(INTEGER, ~"2")),
                    '1' => return Some(TokenValue::new(INTEGER, ~"1")),
                    '0' => return Some(TokenValue::new(INTEGER, ~"0")),
                    _ => {

                        let mut current = ~"";
                        let mut previous = ~"";

                        // Push the current character
                        current.push_char(c);

                        loop {
                            // Try the next character. If we get a valid identifier
                            // than we can move the position of the iterator.
                            match (*self.iter).peek() {
                                Some(character) => {
                                    // Lets save the current buffer as the previous.
                                    // This ensures that if this character makes the invalidation,
                                    // we can return the previously valid string.
                                    previous = current.clone();

                                    // Push the new chracter onto the current buffer.
                                    current.push_char(character);

                                    if is_iden(current) {
                                        (*self.iter).next();
                                    }

                                    if !is_iden(current) && is_iden(previous) {
                                        return Some(TokenValue::new(IDEN, previous));
                                    }
                                },
                                None => { break }
                            }
                        }

                        if !is_iden(current) && is_iden(previous) {
                            return Some(TokenValue::new(IDEN, previous));
                        }
                    }
                }
            }
        }
        None
    }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"+");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
        assert!(lex.next_token().unwrap().value == ~":");
        assert!(lex.next_token().unwrap().value == ~"8");
        assert!(lex.next_token().unwrap().value == ~"3");
        assert!(lex.next_token().unwrap().value == ~"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_forget_whitespace() {
        let mut lex = Lexer::new(&"( )");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_count_lines() {
        let mut lex = Lexer::new(&"(\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");

        assert_eq!(unsafe { (*lex.iter).line }, 2);
    }
}<commit_msg>more tests<commit_after>use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;
use std::str::CharRange;

pub struct TokenValue {
    token: Token,
    value: ~str
}

impl TokenValue {
    pub fn new(tok: Token, val: ~str) -> TokenValue {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

struct LexerIterator<'a> {
    string: &'a str,
    pos: uint,
    line: uint,
    next: uint,
    current: Option<char>,
    peek: Option<char>,
    previous: Option<char>
}

impl<'a> LexerIterator<'a> {
    pub fn new(string: &'a str) -> LexerIterator<'a> {
        LexerIterator {
            string: string,
            pos: 0,
            next: 0,
            line: 1,
            current: None,
            peek: None,
            previous: None
        }
    }

    pub fn next(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.pos = next;

            if self.current.is_some() {
                self.previous = self.current;
            }

            self.current = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.peek = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut LexerIterator<'a>,
    done: bool
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            iter: unsafe { transmute(~LexerIterator::new(input)) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue> {
        unsafe {
            for c in *self.iter {
                match c {
                    ' ' => continue,
                    '\r' => continue,
                    '\n' => {
                        (*self.iter).line += 1;
                        continue
                    },
                    '(' => return Some(TokenValue::new(LPAREN, ~"(")),
                    ')' => return Some(TokenValue::new(RPAREN, ~")")),
                    '+' => return Some(TokenValue::new(PLUS, ~"+")),
                    '-' => return Some(TokenValue::new(MINUS, ~"-")),
                    ':' => return Some(TokenValue::new(COLON, ~":")),
                    '9' => return Some(TokenValue::new(INTEGER, ~"9")),
                    '8' => return Some(TokenValue::new(INTEGER, ~"8")),
                    '7' => return Some(TokenValue::new(INTEGER, ~"7")),
                    '6' => return Some(TokenValue::new(INTEGER, ~"6")),
                    '5' => return Some(TokenValue::new(INTEGER, ~"5")),
                    '4' => return Some(TokenValue::new(INTEGER, ~"4")),
                    '3' => return Some(TokenValue::new(INTEGER, ~"3")),
                    '2' => return Some(TokenValue::new(INTEGER, ~"2")),
                    '1' => return Some(TokenValue::new(INTEGER, ~"1")),
                    '0' => return Some(TokenValue::new(INTEGER, ~"0")),
                    _ => {

                        let mut current = ~"";
                        let mut previous = ~"";

                        // Push the current character
                        current.push_char(c);

                        loop {
                            // Try the next character. If we get a valid identifier
                            // than we can move the position of the iterator.
                            match (*self.iter).peek() {
                                Some(character) => {
                                    // Lets save the current buffer as the previous.
                                    // This ensures that if this character makes the invalidation,
                                    // we can return the previously valid string.
                                    previous = current.clone();

                                    // Push the new chracter onto the current buffer.
                                    current.push_char(character);

                                    if is_iden(current) {
                                        (*self.iter).next();
                                    }

                                    if !is_iden(current) && is_iden(previous) {
                                        return Some(TokenValue::new(IDEN, previous));
                                    }
                                },
                                None => { break }
                            }
                        }

                        if !is_iden(current) && is_iden(previous) {
                            return Some(TokenValue::new(IDEN, previous));
                        }
                    }
                }
            }
        }
        None
    }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"+");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
        assert!(lex.next_token().unwrap().value == ~":");
        assert!(lex.next_token().unwrap().value == ~"8");
        assert!(lex.next_token().unwrap().value == ~"3");
        assert!(lex.next_token().unwrap().value == ~"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_forget_whitespace() {
        let mut lex = Lexer::new(&"( )");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_count_lines() {
        let mut lex = Lexer::new(&"(\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");

        assert_eq!(unsafe { (*lex.iter).line }, 2);
    }

    #[test]
    fn should_identify_an_iden_across_lines() {
        let mut lex = Lexer::new(&"(\nlet\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }
}<|endoftext|>


<commit_before>// Initial Rust implementation.

use std::time::Instant;
use std::thread;
use std::sync::mpsc::channel;

fn main() {

    let mut num_steps: i64;
    let mut num_threads: i64;
    let step: f64;
    let mut s: f64;
    let my_pi: f64;
    let arguments = std::env::args();

    num_steps = 100000000;
    num_threads = 1;

// Arguments are an iterator which is a PITA.
    let mut index = 0;
    for argument in arguments {
        if index == 1 {
            num_steps = argument.parse::<i64>().unwrap();
        }
        if index == 2 {
            num_threads = argument.parse::<i64>().unwrap();
        }
        index = index + 1;
    }

    print!("Calculating PI using:\n");
    print!("  {} slices\n", num_steps.to_string());
    print!("  {} threads\n", num_threads.to_string());

    let start = Instant::now();

    let (transmit, receive) = channel();

    s = 0.0;
    step = 1.0/num_steps as f64;

    for rank in 0..num_threads {
        let transmit = transmit.clone();
        thread::spawn(move|| {
            let mut s = 0.0;
            let chunkstart = rank * num_steps / num_threads;
            let chunkend = (rank + 1) * num_steps / num_threads;
// Uncomment to check parallelisation:
//            print!("Thread: {} ", rank);
//            print!("Start: {} ", chunkstart);
//            print!("End: {} ", chunkend-1);
//            print!("Length: {}\n", chunkend - chunkstart);
            for i in chunkstart..chunkend {
                let x = ((i as f64) + 0.5)* step;
                s = s + (4.0/(1.0 + (x*x)));
            }
            transmit.send(s).unwrap();
        });
    }

// Gather results.
    for _ in 0..num_threads {
        let r = receive.recv().unwrap();
        s = s + r;
    }

    my_pi = s * step;

    let stop = Instant::now();

    print!("Obtained value of PI: {}\n", my_pi);
    print!("Time Elapsed: {}.", stop.duration_since(start).as_secs());
    print!("{} seconds\n", stop.duration_since(start).subsec_nanos());

}<commit_msg>Support OMP_NUM_THREADS.<commit_after>// Initial Rust implementation.

use std::time::Instant;
use std::thread;
use std::sync::mpsc::channel;
use std::env;

fn main() {

    let mut num_steps: i64;
    let mut num_threads: i64;
    let step: f64;
    let mut s: f64;
    let my_pi: f64;
    let arguments = std::env::args();

    num_steps = 100000000;

// Check OMP_NUM_THREADS.  If it doesn't exist, default to threads = 1.
    match env::var("OMP_NUM_THREADS") {
        Ok(val) => num_threads=val.parse::<i64>().unwrap(),
        Err(_) => num_threads = 1,
    }

// Arguments are an iterator which is a PITA.
    let mut index = 0;
    for argument in arguments {
        if index == 1 {
            num_steps = argument.parse::<i64>().unwrap();
        }

// Treat second argument as a number of threads that overrides OMP_NUM_THREADS.
        if index == 2 {
            num_threads = argument.parse::<i64>().unwrap();
        }
        index = index + 1;
    }

    print!("Calculating PI using:\n");
    print!("  {} slices\n", num_steps.to_string());
    print!("  {} threads\n", num_threads.to_string());

    let start = Instant::now();

    let (transmit, receive) = channel();

    s = 0.0;
    step = 1.0/num_steps as f64;

    for rank in 0..num_threads {
        let transmit = transmit.clone();
        thread::spawn(move|| {
            let mut s = 0.0;
            let chunkstart = rank * num_steps / num_threads;
            let chunkend = (rank + 1) * num_steps / num_threads;
// Uncomment to check parallelisation:
//            print!("Thread: {} ", rank);
//            print!("Start: {} ", chunkstart);
//            print!("End: {} ", chunkend-1);
//            print!("Length: {}\n", chunkend - chunkstart);
            for i in chunkstart..chunkend {
                let x = ((i as f64) + 0.5)* step;
                s = s + (4.0/(1.0 + (x*x)));
            }
            transmit.send(s).unwrap();
        });
    }

// Gather results.
    for _ in 0..num_threads {
        let r = receive.recv().unwrap();
        s = s + r;
    }

    my_pi = s * step;

    let stop = Instant::now();

    print!("Obtained value of PI: {}\n", my_pi);
    print!("Time Elapsed: {}.", stop.duration_since(start).as_secs());
    print!("{} seconds\n", stop.duration_since(start).subsec_nanos());

}<|endoftext|>


<commit_before>use nix::poll::{PollFlags, poll, PollFd};
use nix::unistd::{write, pipe, close};

#[test]
fn test_poll() {
    let (r, w) = pipe().unwrap();
    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];

    // Poll an idle pipe.  Should timeout
    let nfds = poll(&mut fds, 100).unwrap();
    assert_eq!(nfds, 0);
    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));

    write(w, b".").unwrap();

    // Poll a readable pipe.  Should return an event.
    let nfds = poll(&mut fds, 100).unwrap();
    assert_eq!(nfds, 1);
    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
}

#[test]
fn test_poll_debug() {
    assert_eq!(format!("{:?}", PollFd::new(0, PollFlags::empty())),
               "PollFd { fd: 0, events: (empty), revents: (empty) }");
    assert_eq!(format!("{:?}", PollFd::new(1, PollFlags::POLLIN)),
               "PollFd { fd: 1, events: POLLIN, revents: (empty) }");

    // Testing revents requires doing some I/O
    let (r, w) = pipe().unwrap();
    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
    write(w, b" ").unwrap();
    close(w).unwrap();
    poll(&mut fds, -1).unwrap();
    assert_eq!(format!("{:?}", fds[0]),
               format!("PollFd {{ fd: {}, events: POLLIN, revents: POLLIN | POLLHUP }}", r));
    close(r).unwrap();
}

// ppoll(2) is the same as poll except for how it handles timeouts and signals.
// Repeating the test for poll(2) should be sufficient to check that our
// bindings are correct.
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "linux"))]
#[test]
fn test_ppoll() {
    use nix::poll::ppoll;
    use nix::sys::signal::SigSet;
    use nix::sys::time::{TimeSpec, TimeValLike};

    let timeout = TimeSpec::milliseconds(1);
    let (r, w) = pipe().unwrap();
    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];

    // Poll an idle pipe.  Should timeout
    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
    assert_eq!(nfds, 0);
    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));

    write(w, b".").unwrap();

    // Poll a readable pipe.  Should return an event.
    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
    assert_eq!(nfds, 1);
    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
}
<commit_msg>Remove test of impl Debug for PollFd<commit_after>use nix::poll::{PollFlags, poll, PollFd};
use nix::unistd::{write, pipe};

#[test]
fn test_poll() {
    let (r, w) = pipe().unwrap();
    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];

    // Poll an idle pipe.  Should timeout
    let nfds = poll(&mut fds, 100).unwrap();
    assert_eq!(nfds, 0);
    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));

    write(w, b".").unwrap();

    // Poll a readable pipe.  Should return an event.
    let nfds = poll(&mut fds, 100).unwrap();
    assert_eq!(nfds, 1);
    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
}

// ppoll(2) is the same as poll except for how it handles timeouts and signals.
// Repeating the test for poll(2) should be sufficient to check that our
// bindings are correct.
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "linux"))]
#[test]
fn test_ppoll() {
    use nix::poll::ppoll;
    use nix::sys::signal::SigSet;
    use nix::sys::time::{TimeSpec, TimeValLike};

    let timeout = TimeSpec::milliseconds(1);
    let (r, w) = pipe().unwrap();
    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];

    // Poll an idle pipe.  Should timeout
    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
    assert_eq!(nfds, 0);
    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));

    write(w, b".").unwrap();

    // Poll a readable pipe.  Should return an event.
    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
    assert_eq!(nfds, 1);
    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::iter::Empty;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;

use command_buffer::Submission;
use device::Device;
use format::ClearValue;
use format::FormatDesc;
use format::FormatTy;
use image::sys::Dimensions;
use image::sys::ImageCreationError;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::AccessRange;
use image::traits::GpuAccessResult;
use image::traits::Image;
use image::traits::ImageClearValue;
use image::traits::ImageContent;
use image::traits::ImageView;
use image::traits::Transition;
use memory::DeviceMemory;
use sync::Sharing;

#[derive(Debug)]
pub struct AttachmentImage<F> {
    image: UnsafeImage,
    view: UnsafeImageView,
    memory: DeviceMemory,
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Should be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,

    guarded: Mutex<Guarded>,
}

#[derive(Debug)]
struct Guarded {
    correct_layout: bool,
    latest_submission: Option<Weak<Submission>>,    // TODO: can use `Weak::new()` once it's stabilized
}

impl<F> AttachmentImage<F> {
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            transfer_source: true,
            sampled: true,
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            input_attachment: true,
            .. Usage::none()
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc(device, &mem_ty, mem_reqs.size));
        unsafe { try!(image.bind_memory(&mem, 0)); }

        let view = unsafe {
            try!(UnsafeImageView::new(&image, 0 .. 1, 0 .. 1))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
            guarded: Mutex::new(Guarded {
                correct_layout: false,
                latest_submission: None,
            }),
        }))
    }

    #[inline]
    pub fn dimensions(&self) -> Dimensions {
        self.image.dimensions()
    }
}

unsafe impl<F> Image for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn inner_image(&self) -> &UnsafeImage {
        &self.image
    }

    #[inline]
    fn blocks(&self, _: Range<u32>, _: Range<u32>) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn block_mipmap_levels_range(&self, block: (u32, u32)) -> Range<u32> {
        0 .. 1
    }

    #[inline]
    fn block_array_layers_range(&self, block: (u32, u32)) -> Range<u32> {
        0 .. 1
    }

    #[inline]
    fn initial_layout(&self, _: (u32, u32), _: Layout) -> (Layout, bool, bool) {
        (self.attachment_layout, false, false)
    }

    #[inline]
    fn final_layout(&self, _: (u32, u32), _: Layout) -> (Layout, bool, bool) {
        (self.attachment_layout, false, false)
    }

    fn needs_fence(&self, access: &mut Iterator<Item = AccessRange>) -> Option<bool> {
        Some(false)
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>,
                         submission: &Arc<Submission>) -> GpuAccessResult
    {
        let mut guarded = self.guarded.lock().unwrap();

        let dependency = mem::replace(&mut guarded.latest_submission, Some(Arc::downgrade(submission)));
        let dependency = dependency.and_then(|d| d.upgrade());

        let transition = if !guarded.correct_layout {
            vec![Transition {
                block: (0, 0),
                from: Layout::Undefined,
                to: self.attachment_layout,
            }]
        } else {
            vec![]
        };

        guarded.correct_layout = true;

        GpuAccessResult {
            dependencies: if let Some(dependency) = dependency {
                vec![dependency]
            } else {
                vec![]
            },
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
            before_transitions: transition,
            after_transitions: vec![],
        }
    }
}

unsafe impl<F> ImageClearValue<F::ClearValue> for AttachmentImage<F>
    where F: FormatDesc + 'static + Send + Sync
{
    #[inline]
    fn decode(&self, value: F::ClearValue) -> Option<ClearValue> {
        Some(self.format.decode_clear_value(value))
    }
}

unsafe impl<P, F> ImageContent<P> for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F: 'static> ImageView for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn parent(&self) -> &Image {
        self
    }

    #[inline]
    fn parent_arc(me: &Arc<Self>) -> Arc<Image> where Self: Sized {
        me.clone() as Arc<_>
    }

    #[inline]
    fn blocks(&self) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn inner_view(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}
<commit_msg>Documentation and adjustements for AttachmentImage<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Image whose purpose is to be used as a framebuffer attachment.
//!
//! This module declares the `AttachmentImage` type. It is a safe wrapper around `UnsafeImage`
//! and implements all the relevant image traits.
//!
//! The image is always two-dimensional and has only one mipmap, but it can have any kind of
//! format. Trying to use a format that the backend doesn't support for rendering will result in
//! an error being returned when creating the image. Once you have an `AttachmentImage`, you are
//! guaranteed that you will be able to draw on it.
//!
//! The template parameter of `AttachmentImage` is a type that describes the format of the image.

use std::mem;
use std::iter::Empty;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;

use command_buffer::Submission;
use device::Device;
use format::ClearValue;
use format::FormatDesc;
use format::FormatTy;
use image::sys::Dimensions;
use image::sys::ImageCreationError;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::AccessRange;
use image::traits::GpuAccessResult;
use image::traits::Image;
use image::traits::ImageClearValue;
use image::traits::ImageContent;
use image::traits::ImageView;
use image::traits::Transition;
use memory::DeviceMemory;
use sync::Sharing;

/// Image whose purpose is to be used as a framebuffer attachment.
#[derive(Debug)]
pub struct AttachmentImage<F> {
    // Inner implementation.
    image: UnsafeImage,

    // We maintain a view of the whole image since we will need it when rendering.
    view: UnsafeImageView,

    // Memory used to back the image.
    memory: DeviceMemory,

    // Format.
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Should be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,

    // Additional info behind a mutex.
    guarded: Mutex<Guarded>,
}

#[derive(Debug)]
struct Guarded {
    // If false, the image is still in the undefined layout.
    correct_layout: bool,

    // The latest submission that used the image. Used for synchronization purposes.
    latest_submission: Option<Weak<Submission>>,    // TODO: can use `Weak::new()` once it's stabilized
}

impl<F> AttachmentImage<F> {
    /// Creates a new image with the given dimensions and format.
    ///
    /// Returns an error if the dimensions are too large or if the backend doesn't support this
    /// format as a framebuffer attachment.
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            transfer_source: true,
            sampled: true,
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            input_attachment: true,
            .. Usage::none()
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc(device, &mem_ty, mem_reqs.size));
        unsafe { try!(image.bind_memory(&mem, 0)); }

        let view = unsafe {
            try!(UnsafeImageView::new(&image, 0 .. 1, 0 .. 1))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
            guarded: Mutex::new(Guarded {
                correct_layout: false,
                latest_submission: None,
            }),
        }))
    }

    /// Returns the dimensions of the image.
    #[inline]
    pub fn dimensions(&self) -> [u32; 2] {
        let dims = self.image.dimensions();
        [dims.width(), dims.height()]
    }
}

unsafe impl<F> Image for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn inner_image(&self) -> &UnsafeImage {
        &self.image
    }

    #[inline]
    fn blocks(&self, _: Range<u32>, _: Range<u32>) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn block_mipmap_levels_range(&self, block: (u32, u32)) -> Range<u32> {
        0 .. 1
    }

    #[inline]
    fn block_array_layers_range(&self, block: (u32, u32)) -> Range<u32> {
        0 .. 1
    }

    #[inline]
    fn initial_layout(&self, _: (u32, u32), _: Layout) -> (Layout, bool, bool) {
        (self.attachment_layout, false, false)
    }

    #[inline]
    fn final_layout(&self, _: (u32, u32), _: Layout) -> (Layout, bool, bool) {
        (self.attachment_layout, false, false)
    }

    fn needs_fence(&self, access: &mut Iterator<Item = AccessRange>) -> Option<bool> {
        Some(false)
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>,
                         submission: &Arc<Submission>) -> GpuAccessResult
    {
        let mut guarded = self.guarded.lock().unwrap();

        let dependency = mem::replace(&mut guarded.latest_submission, Some(Arc::downgrade(submission)));
        let dependency = dependency.and_then(|d| d.upgrade());

        let transition = if !guarded.correct_layout {
            vec![Transition {
                block: (0, 0),
                from: Layout::Undefined,
                to: self.attachment_layout,
            }]
        } else {
            vec![]
        };

        guarded.correct_layout = true;

        GpuAccessResult {
            dependencies: if let Some(dependency) = dependency {
                vec![dependency]
            } else {
                vec![]
            },
            additional_wait_semaphore: None,
            additional_signal_semaphore: None,
            before_transitions: transition,
            after_transitions: vec![],
        }
    }
}

unsafe impl<F> ImageClearValue<F::ClearValue> for AttachmentImage<F>
    where F: FormatDesc + 'static + Send + Sync
{
    #[inline]
    fn decode(&self, value: F::ClearValue) -> Option<ClearValue> {
        Some(self.format.decode_clear_value(value))
    }
}

unsafe impl<P, F> ImageContent<P> for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F: 'static> ImageView for AttachmentImage<F> where F: 'static + Send + Sync {
    #[inline]
    fn parent(&self) -> &Image {
        self
    }

    #[inline]
    fn parent_arc(me: &Arc<Self>) -> Arc<Image> where Self: Sized {
        me.clone() as Arc<_>
    }

    #[inline]
    fn blocks(&self) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn inner_view(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}
<|endoftext|>


<commit_before>extern crate kcp;
extern crate time as ctime;
extern crate rand;

use std::collections::VecDeque;
use std::io;
use std::io::{Read, Write};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time;

use kcp::KCP;

#[inline]
fn clock() -> u32 {
    let timespec = ctime::get_time();
    let mills = timespec.sec * 1000 + timespec.nsec as i64 / 1000 / 1000;
    mills as u32
}

#[derive(Default)]
struct DelayPacket {
    data: Vec<u8>,
    ts: u32,
}

impl DelayPacket {
    fn new() -> DelayPacket {
        Default::default()
    }
}

struct LatencySimulator {
    tx: u32,
    current: u32,
    lost_rate: u32,
    rtt_min: u32,
    rtt_max: u32,
    nmax: u32,
    delay_tunnel: VecDeque<DelayPacket>,
    rng: Random,
}

impl LatencySimulator {
    fn new(lost_rate: u32, rtt_min: u32, rtt_max: u32, nmax: u32) -> LatencySimulator {
        LatencySimulator {
            tx: 0,
            current: clock(),
            lost_rate: lost_rate / 2,
            rtt_min: rtt_min / 2,
            rtt_max: rtt_max / 2,
            nmax: nmax,
            delay_tunnel: VecDeque::new(),
            rng: Random::new(100),
        }
    }
}

impl Write for LatencySimulator {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tx += 1;
        if self.rng.uniform() < self.lost_rate {
            return Err(io::Error::new(io::ErrorKind::Other, "lost"));
        }
        if self.delay_tunnel.len() >= self.nmax as usize {
            return Err(io::Error::new(io::ErrorKind::Other,
                                      format!("exceeded nmax: {}", self.delay_tunnel.len())));
        }
        let mut pkt = DelayPacket::new();
        self.current = clock();
        let mut delay = self.rtt_min;
        if self.rtt_max > self.rtt_min {
            delay += rand::random::<u32>() % (self.rtt_max - self.rtt_min);
        }
        pkt.ts = self.current + delay;
        pkt.data.extend_from_slice(buf);
        self.delay_tunnel.push_back(pkt);

        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Read for LatencySimulator {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let len: usize;
        if let Some(pkt) = self.delay_tunnel.front() {
            self.current = clock();
            if self.current < pkt.ts {
                return Err(io::Error::new(io::ErrorKind::Other,
                                          format!("current({}) < ts({})", self.current, pkt.ts)));
            }
            len = pkt.data.len();
            if len > buf.len() {
                return Err(io::Error::new(io::ErrorKind::Other,
                                          format!("buf_size({}) < pkt_size({})", buf.len(), len)));
            }
            let buf = &mut buf[..len];
            buf.copy_from_slice(&pkt.data[..]);
        } else {
            return Err(io::Error::new(io::ErrorKind::Other, "empty"));
        }

        self.delay_tunnel.pop_front();
        Ok(len)
    }
}

#[test]
fn kcp_test() {
    let mut results: Vec<String> = Vec::new();
    results.push(test("default"));
    results.push(test("normal"));
    results.push(test("fast"));
    for result in results {
        println!("{}", result);
    }
}

fn test(mode: &str) -> String {

    let alice_to_bob = Arc::new(Mutex::new(LatencySimulator::new(10, 60, 125, 1000)));
    let bob_to_alice = Arc::new(Mutex::new(LatencySimulator::new(10, 60, 125, 1000)));

    let alice_sends = alice_to_bob.clone();
    let bob_sends = bob_to_alice.clone();
    let mut alice = KCP::new(0x11223344, alice_sends);
    let mut bob = KCP::new(0x11223344, bob_sends);

    let mut current = clock();
    let mut slap = current + 20;
    let mut index: u32 = 0;
    let mut next: u32 = 0;
    let mut sumrtt: i64 = 0;
    let mut count = 0;
    let mut maxrtt = 0;

    alice.wndsize(128, 128);
    bob.wndsize(128, 128);

    match mode {
        "default" => {
            alice.nodelay(0, 10, 0, false);
            bob.nodelay(0, 10, 0, false);
        }
        "normal" => {
            alice.nodelay(0, 10, 0, true);
            bob.nodelay(0, 10, 0, true);
        }
        "fast" => {
            alice.nodelay(1, 10, 2, true);
            bob.nodelay(1, 10, 2, true);
        }
        _ => {}
    };

    let mut buffer: [u8; 2000] = [0; 2000];
    let mut ts1 = clock();

    loop {
        thread::sleep(time::Duration::from_millis(1));
        current = clock();

        alice.update(clock());
        bob.update(clock());

        while current >= slap {
            let mut p: usize = 0;
            encode32u(&mut buffer[..], &mut p, index);
            index += 1;
            encode32u(&mut buffer[..], &mut p, current);
            alice.send(&buffer[..8]);
            slap += 20;
        }

        let a2b = alice_to_bob.clone();
        let mut a2b = a2b.lock().unwrap();

        let b2a = bob_to_alice.clone();
        let mut b2a = b2a.lock().unwrap();

        loop {
            match a2b.read(&mut buffer[..]) {
                Ok(hr) => {
                    bob.input(&buffer[..hr]);
                }
                Err(e) => break,
            };
        }

        loop {
            match b2a.read(&mut buffer[..]) {
                Ok(hr) => {
                    alice.input(&buffer[..hr]);
                }
                Err(e) => break,
            }
        }

        loop {
            match bob.recv(&mut buffer[..10]) {
                Ok(hr) => {
                    bob.send(&buffer[..hr]);
                }
                Err(e) => break,
            }
        }

        loop {
            match alice.recv(&mut buffer[..10]) {
                Ok(hr) => {
                    let mut p: usize = 0;
                    let sn = decode32u(&buffer, &mut p);
                    let ts = decode32u(&buffer, &mut p);
                    let rtt = current - ts;
                    if sn != next {
                        println!("ERROR sn {}<->{}", count, next);
                        return "err".to_string();
                    }
                    next += 1;
                    sumrtt += rtt as i64;
                    count += 1;
                    if rtt > maxrtt {
                        maxrtt = rtt;
                    }
                    println!("[RECV] mode={} sn={} rtt={}", mode, sn, rtt);
                }
                Err(e) => break,
            }
        }
        if next > 1000 {
            break;
        }
    }

    ts1 = clock() - ts1;
    format!("{} mode result ({}ms):\n", mode, ts1) +
    &format!("avgrtt={} maxrtt={}", sumrtt / count, maxrtt)
}

#[inline]
fn decode32u(buf: &[u8], p: &mut usize) -> u32 {
    let n = (buf[*p] as u32) | (buf[*p + 1] as u32) << 8 | (buf[*p + 2] as u32) << 16 |
            (buf[*p + 3] as u32) << 24;
    *p += 4;
    u32::from_le(n)
}

#[inline]
fn encode32u(buf: &mut [u8], p: &mut usize, n: u32) {
    let n = n.to_le();
    buf[*p] = n as u8;
    buf[*p + 1] = (n >> 8) as u8;
    buf[*p + 2] = (n >> 16) as u8;
    buf[*p + 3] = (n >> 24) as u8;
    *p += 4;
}

fn to_hex_string(bytes: &[u8]) {
    let mut i = 0;
    for b in bytes {
        print!("0x{:02X} ", b);
        i = i + 1;
        if i % 4 == 0 {
            println!("");
        }
    }
}

struct Random {
    size: usize,
    seeds: Vec<u32>,
}

impl Random {
    fn new(n: usize) -> Random {
        let mut r = Random {
            size: 0,
            seeds: Vec::new(),
        };
        r.seeds.resize(n, 0);
        r
    }

    fn uniform(&mut self) -> u32 {
        if self.seeds.len() == 0 {
            return 0;
        }
        if self.size == 0 {
            for i in 0..self.seeds.len() {
                self.seeds[i] = i as u32;
            }
            self.size = self.seeds.len();
        }
        let i = rand::random::<usize>() % self.size;
        let x = self.seeds[i];
        self.size -= 1;
        self.seeds[i] = self.seeds[self.size];
        x
    }
}
<commit_msg>Fix compiler warnings<commit_after>extern crate kcp;
extern crate time as ctime;
extern crate rand;

use std::collections::VecDeque;
use std::io::{self, Read, Write};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time;

use kcp::KCP;

#[inline]
fn clock() -> u32 {
    let timespec = ctime::get_time();
    let mills = timespec.sec * 1000 + timespec.nsec as i64 / 1000 / 1000;
    mills as u32
}

#[derive(Default)]
struct DelayPacket {
    data: Vec<u8>,
    ts: u32,
}

impl DelayPacket {
    fn new() -> DelayPacket {
        Default::default()
    }
}

struct LatencySimulator {
    tx: u32,
    current: u32,
    lost_rate: u32,
    rtt_min: u32,
    rtt_max: u32,
    nmax: u32,
    delay_tunnel: VecDeque<DelayPacket>,
    rng: Random,
}

impl LatencySimulator {
    fn new(lost_rate: u32, rtt_min: u32, rtt_max: u32, nmax: u32) -> LatencySimulator {
        LatencySimulator {
            tx: 0,
            current: clock(),
            lost_rate: lost_rate / 2,
            rtt_min: rtt_min / 2,
            rtt_max: rtt_max / 2,
            nmax: nmax,
            delay_tunnel: VecDeque::new(),
            rng: Random::new(100),
        }
    }
}

impl Write for LatencySimulator {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tx += 1;
        if self.rng.uniform() < self.lost_rate {
            return Err(io::Error::new(io::ErrorKind::Other, "lost"));
        }
        if self.delay_tunnel.len() >= self.nmax as usize {
            return Err(io::Error::new(io::ErrorKind::Other,
                                      format!("exceeded nmax: {}", self.delay_tunnel.len())));
        }
        let mut pkt = DelayPacket::new();
        self.current = clock();
        let mut delay = self.rtt_min;
        if self.rtt_max > self.rtt_min {
            delay += rand::random::<u32>() % (self.rtt_max - self.rtt_min);
        }
        pkt.ts = self.current + delay;
        pkt.data.extend_from_slice(buf);
        self.delay_tunnel.push_back(pkt);

        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Read for LatencySimulator {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let len: usize;
        if let Some(pkt) = self.delay_tunnel.front() {
            self.current = clock();
            if self.current < pkt.ts {
                return Err(io::Error::new(io::ErrorKind::Other,
                                          format!("current({}) < ts({})", self.current, pkt.ts)));
            }
            len = pkt.data.len();
            if len > buf.len() {
                return Err(io::Error::new(io::ErrorKind::Other,
                                          format!("buf_size({}) < pkt_size({})", buf.len(), len)));
            }
            let buf = &mut buf[..len];
            buf.copy_from_slice(&pkt.data[..]);
        } else {
            return Err(io::Error::new(io::ErrorKind::Other, "empty"));
        }

        self.delay_tunnel.pop_front();
        Ok(len)
    }
}

#[test]
fn kcp_test() {
    let mut results: Vec<String> = Vec::new();
    results.push(test("default"));
    results.push(test("normal"));
    results.push(test("fast"));
    for result in results {
        println!("{}", result);
    }
}

fn test(mode: &str) -> String {

    let alice_to_bob = Arc::new(Mutex::new(LatencySimulator::new(10, 60, 125, 1000)));
    let bob_to_alice = Arc::new(Mutex::new(LatencySimulator::new(10, 60, 125, 1000)));

    let alice_sends = alice_to_bob.clone();
    let bob_sends = bob_to_alice.clone();
    let mut alice = KCP::new(0x11223344, alice_sends);
    let mut bob = KCP::new(0x11223344, bob_sends);

    let mut current = clock();
    let mut slap = current + 20;
    let mut index: u32 = 0;
    let mut next: u32 = 0;
    let mut sumrtt: i64 = 0;
    let mut count = 0;
    let mut maxrtt = 0;

    alice.wndsize(128, 128);
    bob.wndsize(128, 128);

    match mode {
        "default" => {
            alice.nodelay(0, 10, 0, false);
            bob.nodelay(0, 10, 0, false);
        }
        "normal" => {
            alice.nodelay(0, 10, 0, true);
            bob.nodelay(0, 10, 0, true);
        }
        "fast" => {
            alice.nodelay(1, 10, 2, true);
            bob.nodelay(1, 10, 2, true);
        }
        _ => {}
    };

    let mut buffer: [u8; 2000] = [0; 2000];
    let mut ts1 = clock();

    'outer: loop {
        thread::sleep(time::Duration::from_millis(1));
        current = clock();

        alice.update(clock());
        bob.update(clock());

        while current >= slap {
            let mut p: usize = 0;
            encode32u(&mut buffer[..], &mut p, index);
            index += 1;
            encode32u(&mut buffer[..], &mut p, current);
            alice.send(&buffer[..8]).unwrap();
            slap += 20;
        }

        let a2b = alice_to_bob.clone();
        let mut a2b = a2b.lock().unwrap();

        let b2a = bob_to_alice.clone();
        let mut b2a = b2a.lock().unwrap();

        loop {
            match a2b.read(&mut buffer[..]) {
                Ok(hr) => {
                    bob.input(&buffer[..hr]);
                }
                Err(_) => break,
            };
        }

        loop {
            match b2a.read(&mut buffer[..]) {
                Ok(hr) => {
                    alice.input(&buffer[..hr]);
                }
                Err(_) => break,
            }
        }

        loop {
            match bob.recv(&mut buffer[..10]) {
                Ok(hr) => {
                    bob.send(&buffer[..hr]).unwrap();
                }
                Err(_) => break,
            }
        }

        loop {
            match alice.recv(&mut buffer[..10]) {
                Ok(_) => {
                    let mut p: usize = 0;
                    let sn = decode32u(&buffer, &mut p);
                    let ts = decode32u(&buffer, &mut p);
                    let rtt = current - ts;
                    if sn != next {
                        println!("ERROR sn {}<->{}", count, next);
                        return "err".to_string();
                    }
                    next += 1;
                    sumrtt += rtt as i64;
                    count += 1;
                    if rtt > maxrtt {
                        maxrtt = rtt;
                    }
                    println!("[RECV] mode={} sn={} rtt={}", mode, sn, rtt);
                    if next > 1000 {
                        break 'outer;
                    }
                }
                Err(_) => break,
            }
        }
    }

    ts1 = clock() - ts1;
    format!("{} mode result ({}ms):\n", mode, ts1) +
    &format!("avgrtt={} maxrtt={}", sumrtt / count, maxrtt)
}

#[inline]
fn decode32u(buf: &[u8], p: &mut usize) -> u32 {
    let n = (buf[*p] as u32) | (buf[*p + 1] as u32) << 8 | (buf[*p + 2] as u32) << 16 |
            (buf[*p + 3] as u32) << 24;
    *p += 4;
    u32::from_le(n)
}

#[inline]
fn encode32u(buf: &mut [u8], p: &mut usize, n: u32) {
    let n = n.to_le();
    buf[*p] = n as u8;
    buf[*p + 1] = (n >> 8) as u8;
    buf[*p + 2] = (n >> 16) as u8;
    buf[*p + 3] = (n >> 24) as u8;
    *p += 4;
}

struct Random {
    size: usize,
    seeds: Vec<u32>,
}

impl Random {
    fn new(n: usize) -> Random {
        let mut r = Random {
            size: 0,
            seeds: Vec::new(),
        };
        r.seeds.resize(n, 0);
        r
    }

    fn uniform(&mut self) -> u32 {
        if self.seeds.len() == 0 {
            return 0;
        }
        if self.size == 0 {
            for i in 0..self.seeds.len() {
                self.seeds[i] = i as u32;
            }
            self.size = self.seeds.len();
        }
        let i = rand::random::<usize>() % self.size;
        let x = self.seeds[i];
        self.size -= 1;
        self.seeds[i] = self.seeds[self.size];
        x
    }
}
<|endoftext|>


<commit_before>
/// Trait for fixed size arrays.
///
/// This trait is implemented for some specific array sizes, see
/// the implementor list below. At the current state of Rust we can't
/// make this fully general for every array size.
///
/// The following crate features add more array sizes (and they are not
/// enabled by default due to their impact on compliation speed).
///
/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented
///   (a few in this range are included by default).
/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented
///   (a few in this range are included by default).
pub unsafe trait Array {
    /// The array’s element type
    type Item;
    #[doc(hidden)]
    /// The smallest index type that indexes the array.
    type Index: Index;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

pub trait Index : PartialEq + Copy {
    fn to_usize(self) -> usize;
    fn from(usize) -> Self;
}

use std::slice::{from_raw_parts};

pub trait ArrayExt : Array {
    #[inline(always)]
    fn as_slice(&self) -> &[Self::Item] {
        unsafe {
            from_raw_parts(self.as_ptr(), Self::capacity())
        }
    }
}

impl<A> ArrayExt for A where A: Array { }

impl Index for () {
    #[inline(always)]
    fn to_usize(self) -> usize { 0 }
    #[inline(always)]
    fn from(_ix: usize) ->  Self { () }
}

impl Index for bool {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix != 0 }
}

impl Index for u8 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u8 }
}

impl Index for u16 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u16 }
}

impl Index for u32 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u32 }
}

impl Index for usize {
    #[inline(always)]
    fn to_usize(self) -> usize { self }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix }
}

macro_rules! fix_array_impl {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            #[doc(hidden)]
            #[inline(always)]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            #[doc(hidden)]
            #[inline(always)]
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[doc(hidden)]
            #[inline(always)]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    ($index_type:ty, ) => ();
    ($index_type:ty, $($len:expr,)*) => (
        $(fix_array_impl!($index_type, $len);)*
    );
}

fix_array_impl_recursive!((), 0,);
fix_array_impl_recursive!(bool, 1,);
fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                          15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
                          28, 29, 30, 31, );

#[cfg(not(feature="array-sizes-33-128"))]
fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, );

#[cfg(feature="array-sizes-33-128")]
fix_array_impl_recursive!(u8,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128,
);

#[cfg(not(feature="array-sizes-129-255"))]
fix_array_impl_recursive!(u8, 160, 192, 200, 224,);

#[cfg(feature="array-sizes-129-255")]
fix_array_impl_recursive!(u8,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255,
);

fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,);
// This array size doesn't exist on 16-bit
#[cfg(any(target_pointer_width="32", target_pointer_width="64"))]
fix_array_impl_recursive!(u32, 1 << 16,);

<commit_msg>FIX: Add associated constant for Array's capacity<commit_after>
/// Trait for fixed size arrays.
///
/// This trait is implemented for some specific array sizes, see
/// the implementor list below. At the current state of Rust we can't
/// make this fully general for every array size.
///
/// The following crate features add more array sizes (and they are not
/// enabled by default due to their impact on compliation speed).
///
/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented
///   (a few in this range are included by default).
/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented
///   (a few in this range are included by default).
pub unsafe trait Array {
    /// The array’s element type
    type Item;
    /// The smallest type that can index and tell the length of the array.
    #[doc(hidden)]
    type Index: Index;
    /// The array's element capacity
    const CAPACITY: usize;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

pub trait Index : PartialEq + Copy {
    fn to_usize(self) -> usize;
    fn from(usize) -> Self;
}

use std::slice::{from_raw_parts};

pub trait ArrayExt : Array {
    #[inline(always)]
    fn as_slice(&self) -> &[Self::Item] {
        unsafe {
            from_raw_parts(self.as_ptr(), Self::capacity())
        }
    }
}

impl<A> ArrayExt for A where A: Array { }

impl Index for () {
    #[inline(always)]
    fn to_usize(self) -> usize { 0 }
    #[inline(always)]
    fn from(_ix: usize) ->  Self { () }
}

impl Index for bool {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix != 0 }
}

impl Index for u8 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u8 }
}

impl Index for u16 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u16 }
}

impl Index for u32 {
    #[inline(always)]
    fn to_usize(self) -> usize { self as usize }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix as u32 }
}

impl Index for usize {
    #[inline(always)]
    fn to_usize(self) -> usize { self }
    #[inline(always)]
    fn from(ix: usize) ->  Self { ix }
}

macro_rules! fix_array_impl {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            const CAPACITY: usize = $len;
            #[doc(hidden)]
            #[inline(always)]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            #[doc(hidden)]
            #[inline(always)]
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[doc(hidden)]
            #[inline(always)]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    ($index_type:ty, ) => ();
    ($index_type:ty, $($len:expr,)*) => (
        $(fix_array_impl!($index_type, $len);)*
    );
}

fix_array_impl_recursive!((), 0,);
fix_array_impl_recursive!(bool, 1,);
fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                          15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
                          28, 29, 30, 31, );

#[cfg(not(feature="array-sizes-33-128"))]
fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, );

#[cfg(feature="array-sizes-33-128")]
fix_array_impl_recursive!(u8,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128,
);

#[cfg(not(feature="array-sizes-129-255"))]
fix_array_impl_recursive!(u8, 160, 192, 200, 224,);

#[cfg(feature="array-sizes-129-255")]
fix_array_impl_recursive!(u8,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255,
);

fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,);
// This array size doesn't exist on 16-bit
#[cfg(any(target_pointer_width="32", target_pointer_width="64"))]
fix_array_impl_recursive!(u32, 1 << 16,);

<|endoftext|>


<commit_before>use libc;
use std;

#[repr(C)]
pub struct Color {
  pub opaque: *mut libc::c_void
}

impl Color {
  pub fn new(red: i8, green: i8, blue: i8, alpha: i8) -> Color {
    unsafe {
      let foreign_result = clutter_color_new(red, green, blue, alpha);
      return foreign_result;
    }
  }

  pub fn alloc() -> Color {
    unsafe {
      let foreign_result = clutter_color_alloc();
      return foreign_result;
    }
  }

  pub fn init(&mut self, red: i8, green: i8, blue: i8, alpha: i8) {
    unsafe {
      clutter_color_init(self.opaque, red, green, blue, alpha);
    }
  }

  pub fn equal(&self, other: &Color) -> bool {
    unsafe {
      let foreign_result = clutter_color_equal(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result != 0;
    }
  }

  pub fn hash(&self) -> i32 {
    unsafe {
      let foreign_result = clutter_color_hash(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn from_string(&mut self, name: &str) -> bool {
    unsafe {
      use std::c_str::ToCStr;
      let foreign_result = clutter_color_from_string(self.opaque, name.to_c_str().unwrap() as *mut i8);
      return foreign_result != 0;
    }
  }

  pub fn to_string(&self) -> std::c_str::CString {
    unsafe {
      let foreign_result = clutter_color_to_string(self.opaque as *mut libc::c_void);
      return std::c_str::CString::new(foreign_result as *const i8, false);
    }
  }

  pub fn from_hls(&mut self, hue: f32, luminance: f32, saturation: f32) {
    unsafe {
      clutter_color_from_hls(self.opaque, hue, luminance, saturation);
    }
  }

  pub fn to_hls(&self) -> (f32, f32, f32) {
    unsafe {
      let mut hue:f32 =std::intrinsics::init();
      let mut luminance:f32 =std::intrinsics::init();
      let mut saturation:f32 =std::intrinsics::init();
      clutter_color_to_hls(self.opaque as *mut libc::c_void, &mut hue, &mut luminance, &mut saturation);
      return (hue, luminance, saturation);
    }
  }

  pub fn from_pixel(&mut self, pixel: i32) {
    unsafe {
      clutter_color_from_pixel(self.opaque, pixel);
    }
  }

  pub fn to_pixel(&self) -> i32 {
    unsafe {
      let foreign_result = clutter_color_to_pixel(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn add(&self, other: &Color) -> Color {
    unsafe {
      let foreign_result = clutter_color_add(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn subtract(&self, other: &Color) -> Color {
    unsafe {
      let foreign_result = clutter_color_subtract(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn lighten(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_lighten(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn darken(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_darken(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  pub fn shade(&self, factor: f64) -> Color {
    unsafe {
      let foreign_result = clutter_color_shade(self.opaque as *mut libc::c_void, factor);
      return foreign_result;
    }
  }

  pub fn interpolate(&self, final_color: &Color, progress: f64) -> Color {
    unsafe {
      let foreign_result = clutter_color_interpolate(self.opaque as *mut libc::c_void, final_color.opaque as *mut libc::c_void, progress);
      return foreign_result;
    }
  }
}

extern {
  fn clutter_color_new(red: i8, green: i8, blue: i8, alpha: i8) -> Color;
  fn clutter_color_alloc() -> Color;
  fn clutter_color_init(self_value: *mut libc::c_void, red: i8, green: i8, blue: i8, alpha: i8);
  fn clutter_color_equal(self_value: *mut libc::c_void, other: *mut libc::c_void) -> i32;
  fn clutter_color_hash(self_value: *mut libc::c_void) -> i32;
  fn clutter_color_from_string(self_value: *mut libc::c_void, name: *mut libc::c_char) -> i32;
  fn clutter_color_to_string(self_value: *mut libc::c_void) -> *mut i8;
  fn clutter_color_from_hls(self_value: *mut libc::c_void, hue: f32, luminance: f32, saturation: f32);
  fn clutter_color_to_hls(self_value: *mut libc::c_void, hue: *mut f32, luminance: *mut f32, saturation: *mut f32);
  fn clutter_color_from_pixel(self_value: *mut libc::c_void, pixel: i32);
  fn clutter_color_to_pixel(self_value: *mut libc::c_void) -> i32;
  fn clutter_color_add(self_value: *mut libc::c_void, other: *mut libc::c_void) -> Color;
  fn clutter_color_subtract(self_value: *mut libc::c_void, other: *mut libc::c_void) -> Color;
  fn clutter_color_lighten(self_value: *mut libc::c_void) -> Color;
  fn clutter_color_darken(self_value: *mut libc::c_void) -> Color;
  fn clutter_color_shade(self_value: *mut libc::c_void, factor: f64) -> Color;
  fn clutter_color_interpolate(self_value: *mut libc::c_void, final_color: *mut libc::c_void, progress: f64) -> Color;
}

impl std::clone::Clone for Color {
  fn clone(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_copy(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }
}

extern {
  fn clutter_color_copy(self_value: *mut libc::c_void) -> Color;
}

//FIXME: What was DeepClone and is it still needed?
/*impl DeepClone for Color {
  fn deep_clone(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_copy(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }
}*/

impl std::ops::Drop for Color {
  fn drop(&mut self) {
    unsafe {
      clutter_color_free(self.opaque);
    }
  }
}

extern {
  fn clutter_color_free(self_value: *mut libc::c_void);
}

<commit_msg>Document color mod<commit_after>#![stable]

use libc;
use std;

/// Named colors, for accessing global colors defined by Clutter.
#[repr(C)]
pub enum StaticColor {
  // CGA/EGA color palette
  White       =  0,
  Black       =  1,
  Red         =  2,
  DarkRed     =  3,
  Green       =  4,
  DarkGreen   =  5,
  Blue        =  6,
  DarkBlue    =  7,
  Cyan        =  8,
  DarkCyan    =  9,
  Magenta     = 10,
  DarkMagenta = 11,
  Yellow      = 12,
  DarkYellow  = 13,
  Gray        = 14,
  DarkGray    = 15,
  LightGray   = 16,

  // Tango Icon color palette
  Butter          = 17,
  ButterLight     = 18,
  ButterDark      = 19,
  Orange          = 20,
  OrangeLight     = 21,
  OrangeDark      = 22,
  Chocolate       = 23,
  ChocolateLight  = 24,
  ChocolateDark   = 25,
  Chameleon       = 26,
  ChameleonLight  = 27,
  ChameleonDark   = 28,
  SkyBlue         = 29,
  SkyBlueLight    = 30,
  SkyBlueDark     = 31,
  Plum            = 32,
  PlumLight       = 33,
  PlumDark        = 34,
  ScarletRed      = 35,
  ScarletRedLight = 36,
  ScarletRedDark  = 37,
  Aluminium1      = 38,
  Aluminium2      = 39,
  Aluminium3      = 40,
  Aluminium4      = 41,
  Aluminium5      = 42,
  Aluminium6      = 43,

  // Last color
  Transparent = 44
}

/// Color management and manipulation.
///
/// A Color is expressed as a 4-tuple of values ranging from zero to 255, one
/// for each RGB color channel plus one for the alpha.
///
/// The alpha channel is fully opaque at 255 and fully transparent at 0.
#[repr(C)]
pub struct Color {
  pub opaque: *mut libc::c_void
}

impl Color {
  /// Creates a new Color with the given values.
  ///
  /// _Since 0.8.4_
  pub fn new(red: i8, green: i8, blue: i8, alpha: i8) -> Color {
    unsafe {
      let foreign_result = clutter_color_new(red, green, blue, alpha);
      return foreign_result;
    }
  }

  /// Allocates a new, transparent black Color.
  ///
  /// _Since 1.12_
  pub fn alloc() -> Color {
    unsafe {
      let foreign_result = clutter_color_alloc();
      return foreign_result;
    }
  }

  /// Initializes color with the given values.
  ///
  /// _Since 1.12_
  pub fn init(&mut self, red: i8, green: i8, blue: i8, alpha: i8) {
    unsafe {
      clutter_color_init(self.opaque, red, green, blue, alpha);
    }
  }

  /// Compares two Colors and checks if they are the same.
  ///
  /// _Since 0.2_
  pub fn equal(&self, other: &Color) -> bool {
    unsafe {
      let foreign_result = clutter_color_equal(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result != 0;
    }
  }

  /// Converts a Color to a hash value.
  ///
  /// This can be used in hash tables.
  ///
  /// _Since 1.0_
  pub fn hash(&self) -> i32 {
    unsafe {
      let foreign_result = clutter_color_hash(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Retrieves a static color for the given color name.
  ///
  /// Static colors are created by Clutter and are guaranteed to always be
  /// available and valid. They should never be mutated.
  ///
  /// _Since 1.6_
  pub fn get_static(static_color: StaticColor) -> Color {
    unsafe {
      let foreign_result = clutter_color_get_static(static_color);
      return foreign_result;
    }
  }

  /// Parses a string definition of a color, filling the `red`, `green`, `blue`
  /// and `alpha` channels of color.
  ///
  /// The color is not allocated.
  ///
  /// The format of `str` can be either one of:
  ///
  /// - a standard name (as taken from the X11 rgb.txt file)
  /// - a hex value in the form: `#rgb`, `#rrggbb`, `#rgba`, or `#rrggbbaa`
  /// - a RGB color in the form: `rgb(r, g, b)`
  /// - a RGBA color in the form: `rgba(r, g, b, a)`
  /// - a HSL color in the form: `hsl(h, s, l)`
  /// - a HSLA color in the form: `hsla(h, s, l, a)`
  ///
  /// where `r`, `g`, `b` and `a` are (respectively) the red, green, blue color
  /// intensities and the opacity. The `h`, `s` and `l` are (respectively) the
  /// hue, saturation and luminance values.
  ///
  /// In the `rgb()` and `rgba()` formats, the `r`, `g`, and `b` values are
  /// either integers between 0 and 255, or percentage values in the range
  /// between 0% and 100%; the percentages require the `%` character. The `a`
  /// value, if specified, can only be a floating point value between 0.0 and
  /// 1.0.
  ///
  /// In the `hls()` and `hlsa()` formats, the `h` value (hue) is an angle
  /// between 0 and 360.0 degrees; the `l` and `s` values (luminance and
  /// saturation) are percentage values in the range between 0% and 100%. The
  /// `a` value, if specified, can only be a floating point value between 0.0
  /// and 1.0.
  ///
  /// Whitespace inside the definitions is ignored; no leading whitespace is
  /// allowed.
  ///
  /// If the alpha component is not specified then it is assumed to be set to
  /// be fully opaque.
  ///
  /// _Since 1.0_
  pub fn from_string(&mut self, name: &str) -> bool {
    unsafe {
      use std::c_str::ToCStr;
      let foreign_result = clutter_color_from_string(self.opaque, name.to_c_str().unwrap() as *mut i8);
      return foreign_result != 0;
    }
  }

  /// Returns a textual specification of color in the hexadecimal form `#rrggbbaa`
  ///
  /// _Since 0.2_
  pub fn to_string(&self) -> std::c_str::CString {
    unsafe {
      let foreign_result = clutter_color_to_string(self.opaque as *mut libc::c_void);
      return std::c_str::CString::new(foreign_result as *const i8, false);
    }
  }

  /// Converts a color expressed in HLS (hue, luminance and saturation) values
  /// into a Color.
  pub fn from_hls(&mut self, hue: f32, luminance: f32, saturation: f32) {
    unsafe {
      clutter_color_from_hls(self.opaque, hue, luminance, saturation);
    }
  }

  /// Converts `color` to the HLS format.
  ///
  /// The hue value is in the 0..360 range. The luminance and saturation values
  /// are in the 0..1 range.
  pub fn to_hls(&self) -> (f32, f32, f32) {
    unsafe {
      let mut hue:f32 =std::intrinsics::init();
      let mut luminance:f32 =std::intrinsics::init();
      let mut saturation:f32 =std::intrinsics::init();
      clutter_color_to_hls(self.opaque as *mut libc::c_void, &mut hue, &mut luminance, &mut saturation);
      return (hue, luminance, saturation);
    }
  }

  /// Converts `pixel` from the packed 32-bit integer representation of a four
  /// 8-bit channel color to a Color.
  pub fn from_pixel(&mut self, pixel: i32) {
    unsafe {
      clutter_color_from_pixel(self.opaque, pixel);
    }
  }

  /// Converts `color` into a packed 32-bit integer, containing all four 8-bit
  /// channels used by Color.
  pub fn to_pixel(&self) -> i32 {
    unsafe {
      let foreign_result = clutter_color_to_pixel(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Adds the `other` color to this one and returns the result.
  ///
  /// The alpha channel of result is set as as the maximum value between the
  /// alpha channels of this color and the `other`.
  pub fn add(&self, other: &Color) -> Color {
    unsafe {
      let foreign_result = clutter_color_add(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Subtracts the `other` color from this one and returns the result.
  ///
  /// This method assumes that the components of this color are greater than
  /// the components of the `other`; the result is, otherwise, undefined.
  ///
  /// The alpha channel of the result is set as the minimum value between the
  /// alpha channels of this color and the `other`.
  pub fn subtract(&self, other: &Color) -> Color {
    unsafe {
      let foreign_result = clutter_color_subtract(self.opaque as *mut libc::c_void, other.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Lightens the color by a fixed amount, and returns the result.
  pub fn lighten(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_lighten(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Darkens the color by a fixed amount, and returns the result.
  pub fn darken(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_darken(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }

  /// Shades the color by `factor`, and returns the result.
  pub fn shade(&self, factor: f64) -> Color {
    unsafe {
      let foreign_result = clutter_color_shade(self.opaque as *mut libc::c_void, factor);
      return foreign_result;
    }
  }

  /// Interpolates between this color and the `final` color using `progress`.
  pub fn interpolate(&self, final_color: &Color, progress: f64) -> Color {
    unsafe {
      let foreign_result = clutter_color_interpolate(self.opaque as *mut libc::c_void, final_color.opaque as *mut libc::c_void, progress);
      return foreign_result;
    }
  }
}

extern {
  fn clutter_color_new(red: i8, green: i8, blue: i8, alpha: i8) -> Color;
  fn clutter_color_alloc() -> Color;
  fn clutter_color_init(self_value: *mut libc::c_void, red: i8, green: i8, blue: i8, alpha: i8);
  fn clutter_color_equal(self_value: *mut libc::c_void, other: *mut libc::c_void) -> i32;
  fn clutter_color_hash(self_value: *mut libc::c_void) -> i32;
  fn clutter_color_get_static(static_color: StaticColor) -> Color;
  fn clutter_color_from_string(self_value: *mut libc::c_void, name: *mut libc::c_char) -> i32;
  fn clutter_color_to_string(self_value: *mut libc::c_void) -> *mut i8;
  fn clutter_color_from_hls(self_value: *mut libc::c_void, hue: f32, luminance: f32, saturation: f32);
  fn clutter_color_to_hls(self_value: *mut libc::c_void, hue: *mut f32, luminance: *mut f32, saturation: *mut f32);
  fn clutter_color_from_pixel(self_value: *mut libc::c_void, pixel: i32);
  fn clutter_color_to_pixel(self_value: *mut libc::c_void) -> i32;
  fn clutter_color_add(self_value: *mut libc::c_void, other: *mut libc::c_void) -> Color;
  fn clutter_color_subtract(self_value: *mut libc::c_void, other: *mut libc::c_void) -> Color;
  fn clutter_color_lighten(self_value: *mut libc::c_void) -> Color;
  fn clutter_color_darken(self_value: *mut libc::c_void) -> Color;
  fn clutter_color_shade(self_value: *mut libc::c_void, factor: f64) -> Color;
  fn clutter_color_interpolate(self_value: *mut libc::c_void, final_color: *mut libc::c_void, progress: f64) -> Color;
}

impl std::clone::Clone for Color {
  /// Makes a copy of the color structure.
  ///
  /// _Since 0.2_
  fn clone(&self) -> Color {
    unsafe {
      let foreign_result = clutter_color_copy(self.opaque as *mut libc::c_void);
      return foreign_result;
    }
  }
}

extern {
  fn clutter_color_copy(self_value: *mut libc::c_void) -> Color;
}

impl std::ops::Drop for Color {
  /// Frees a color.
  ///
  /// _Since 0.2_
  fn drop(&mut self) {
    unsafe {
      clutter_color_free(self.opaque);
    }
  }
}

extern {
  fn clutter_color_free(self_value: *mut libc::c_void);
}

<|endoftext|>


<commit_before>use crate::algorithm::AlgorithmType;
use base64::DecodeError;
use crypto_mac::{InvalidKeyLength, MacError};
use serde_json::Error as JsonError;
use std::fmt;
use std::string::FromUtf8Error;

#[derive(Debug)]
pub enum Error {
    AlgorithmMismatch(AlgorithmType, AlgorithmType),
    NoKeyId,
    NoKeyWithKeyId(String),
    Format,
    Base64(DecodeError),
    Json(JsonError),
    Utf8(FromUtf8Error),
    RustCryptoMac(MacError),
    RustCryptoMacKeyLength(InvalidKeyLength),
    #[cfg(feature = "openssl")]
    OpenSsl(openssl::error::ErrorStack),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::AlgorithmMismatch(a, b) => {
                write!(f, "Expected algorithm type {:?} but found {:?}", a, b)
            }
            Error::NoKeyId => write!(f, "No key id found"),
            Error::NoKeyWithKeyId(ref kid) => write!(f, "Key with key id {} not found", kid),
            Error::Format => write!(f, "Format"),
            Error::Base64(ref x) => write!(f, "{}", x),
            Error::Json(ref x) => write!(f, "{}", x),
            Error::Utf8(ref x) => write!(f, "{}", x),
            Error::RustCryptoMac(ref x) => write!(f, "{}", x),
            Error::RustCryptoMacKeyLength(ref x) => write!(f, "{}", x),
            #[cfg(feature = "openssl")]
            Error::OpenSsl(ref x) => write!(f, "{}", x),
        }
    }
}

macro_rules! error_wrap {
    ($f: ty, $e: expr) => {
        impl From<$f> for Error {
            fn from(f: $f) -> Error {
                $e(f)
            }
        }
    };
}

error_wrap!(DecodeError, Error::Base64);
error_wrap!(JsonError, Error::Json);
error_wrap!(FromUtf8Error, Error::Utf8);
error_wrap!(MacError, Error::RustCryptoMac);
error_wrap!(InvalidKeyLength, Error::RustCryptoMacKeyLength);
#[cfg(feature = "openssl")]
error_wrap!(openssl::error::ErrorStack, Error::OpenSsl);
<commit_msg>Remove enum prefix for variants<commit_after>use self::Error::*;
use crate::algorithm::AlgorithmType;
use base64::DecodeError;
use crypto_mac::{InvalidKeyLength, MacError};
use serde_json::Error as JsonError;
use std::fmt;
use std::string::FromUtf8Error;

#[derive(Debug)]
pub enum Error {
    AlgorithmMismatch(AlgorithmType, AlgorithmType),
    NoKeyId,
    NoKeyWithKeyId(String),
    Format,
    Base64(DecodeError),
    Json(JsonError),
    Utf8(FromUtf8Error),
    RustCryptoMac(MacError),
    RustCryptoMacKeyLength(InvalidKeyLength),
    #[cfg(feature = "openssl")]
    OpenSsl(openssl::error::ErrorStack),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            AlgorithmMismatch(a, b) => {
                write!(f, "Expected algorithm type {:?} but found {:?}", a, b)
            }
            NoKeyId => write!(f, "No key id found"),
            NoKeyWithKeyId(ref kid) => write!(f, "Key with key id {} not found", kid),
            Format => write!(f, "Format"),
            Base64(ref x) => write!(f, "{}", x),
            Json(ref x) => write!(f, "{}", x),
            Utf8(ref x) => write!(f, "{}", x),
            RustCryptoMac(ref x) => write!(f, "{}", x),
            RustCryptoMacKeyLength(ref x) => write!(f, "{}", x),
            #[cfg(feature = "openssl")]
            OpenSsl(ref x) => write!(f, "{}", x),
        }
    }
}

macro_rules! error_wrap {
    ($f: ty, $e: expr) => {
        impl From<$f> for Error {
            fn from(f: $f) -> Error {
                $e(f)
            }
        }
    };
}

error_wrap!(DecodeError, Base64);
error_wrap!(JsonError, Json);
error_wrap!(FromUtf8Error, Utf8);
error_wrap!(MacError, RustCryptoMac);
error_wrap!(InvalidKeyLength, RustCryptoMacKeyLength);
#[cfg(feature = "openssl")]
error_wrap!(openssl::error::ErrorStack, Error::OpenSsl);
<|endoftext|>